Support Board
Date/Time: Wed, 27 Nov 2024 02:42:41 +0000
[User Discussion] - TrueLive 2014 for SC V1149 Onwards
View Count: 4190
[2014-06-23 03:52:00] |
Kiwi - Posts: 375 |
IB data comes in two forms: live which is snapshot based so may miss high or low prices with a 100ms snapshot, and true or 5 second data which contains accurate OHLCVT data but is 5 seconds "late." In the past SC has been one of the only charting platforms that let you combine the two to give you "good" IB data using my various TrueLive functions to do it. With version 1148 the SC team chose to improve efficiencies and got rid of the ability to seperately download -TD charts containing 5 second data. Instead we can now select to store 5 second data or live data. If you watch the chart when storing 5 second data you note the bars start 5 seconds after they "should" and you have 5 seconds pauses between updates. All the while your bid / ask is updating as is the SC time and sales. At their suggestion I have created a new dll with a new function TrueLive2014 which you run in SC and will display the updates from the live feed in real time. So the chart stores 5 second data, the 5 second data corrects for any missing ticks, but the T&S information is used to create bars that are on time and responsive. To use it: Save the dll in your data folder Set your Data/Trade Service Settings to: -"Record True Real-Time Data in Intraday Chart" - Number of Stored Time and Sales to > 0 (I use 100) Then > Analysis > Studies > Add Custom Study > and find the study shown Then adjust the colors (first 2 are the up color, next 2 are the down color) Note that I included a version "pvm" for people who use price multipliers or volume multipliers and find that the original version isn't working properly. finding it: http://i.imgur.com/363y4J6.png http://www.sierrachart.com/Download.php?Folder=SupportBoard&download=2850 colors: http://i.imgur.com/5MkI8kF.png http://www.sierrachart.com/Download.php?Folder=SupportBoard&download=2851 Date Time Of Last Edit: 2014-06-23 09:59:17
|
Attachment Deleted. Attachment Deleted. Attachment Deleted. Attachment Deleted. Attachment Deleted. Attachment Deleted. Attachment Deleted. Attachment Deleted. Attachment Deleted. Attachment Deleted. Attachment Deleted. Attachment Deleted. |
[2014-06-23 05:52:53] |
Kiwi - Posts: 375 |
Found issue where, when new session starts it can repeately display a single tick from the Time & Sales (which disappears when you press Insert to refresh the chart). Fixed this by only allowing one T&S bar to be started. /*==========================================================================*/
SCSFExport scsf_TrueLive_2014(SCStudyInterfaceRef sc) { SCFloatArray& O = sc.BaseDataIn[0], H = sc.BaseDataIn[1], L = sc.BaseDataIn[2], C = sc.BaseDataIn[3], V = sc.BaseDataIn[4], T = sc.BaseDataIn[5]; SCSubgraphRef oO = sc.Subgraph[0], oH = sc.Subgraph[1], oL = sc.Subgraph[2], oC = sc.Subgraph[3], oV = sc.Subgraph[4], oT = sc.Subgraph[5]; SCSubgraphRef o = sc.Subgraph[10], h = sc.Subgraph[11], l = sc.Subgraph[12], c = sc.Subgraph[13], v = sc.Subgraph[14], t = sc.Subgraph[15], o2 = sc.Subgraph[22], o3 = sc.Subgraph[23], o4 = sc.Subgraph[24], o5 = sc.Subgraph[25]; if (sc.SetDefaults) { sc.GraphName = "TrueLive 2014"; sc.StudyDescription = "True Live using Custom Chart 2014 Release"; sc.Subgraph[0].Name = "Open"; sc.Subgraph[1].Name = "High"; sc.Subgraph[2].Name = "Low"; sc.Subgraph[3].Name = "Last"; sc.Subgraph[4].Name = "Volume"; sc.Subgraph[5].Name = "# of Trades"; sc.Subgraph[6].Name = "HL"; sc.Subgraph[7].Name = "HLC"; sc.Subgraph[8].Name = "OHLC"; o2.Name="o2"; o3.Name="o3"; o4.Name="o4"; o5.Name="o5"; sc.GraphRegion = 0; // First region sc.GraphDrawType = GDT_CANDLESTICK; sc.DisplayAsMainPriceGraph=1; sc.IsCustomChart = 1; sc.UpdateAlways=1; sc.DrawZeros=0; return; } // sc.FreeDLL = 1; int as = sc.ArraySize-1; int ap = as - 1; int& seqno = sc.PersistVars->i1; int& tnsno = sc.PersistVars->i2; if (sc.UpdateStartIndex == 0) { int os = 0; // os stores the position of the out array tnsno = seqno = 0; sc.ResizeArrays(0); for ( ; os < sc.ArraySize; os++) { sc.AddElements(1); sc.DateTimeOut[os] = sc.BaseDateTimeIn[os]; oO[os] = O[os]; oH[os] = H[os]; oL[os] = L[os]; oC[os] = C[os]; oV[os] = V[os]; oT[os] = T[os]; sc.Subgraph[SC_HL][os] = (oH[os] + oL[os]) / 2; sc.Subgraph[SC_HLC][os] = (oH[os] + oL[os] + oC[os]) / 3; sc.Subgraph[SC_OHLC][os] = (oH[os] + oL[os] + oC[os] + oO[os]) / 4; } } // First deal with underlying data int os = sc.OutArraySize-1; // add an extra bar if the underlying is later than the output bar if( sc.BaseDateTimeIn[as] > sc.DateTimeOut[os] ) { os++; sc.AddElements(1); sc.DateTimeOut[os] = sc.BaseDateTimeIn[as]; oO[os] = oH[os] = oL[os] = oC[os] = O[as]; } int op = os - 1; if (sc.DateTimeOut[os] == sc.BaseDateTimeIn[as]) { // Only apply 5 second data if its changed (ie, dont reset live changes) if(h[os] != H[as] || l[os] != L[as] || c[os] != C[as] || v[os] != V[as]) { tnsno = 0; h[os] = H[as]; l[os] = L[as]; c[os] = C[as]; v[os] = V[as]; // update this bar oO[os] = O[as]; oH[os] = H[as]; oL[os] = L[as]; oC[os] = C[as]; oV[os] = V[as]; oT[os] = T[as]; // match prior bar to 5 second data oO[op] = O[ap]; oH[op] = H[ap]; oL[op] = L[ap]; oC[op] = C[ap]; oV[op] = V[ap]; oT[op] = T[ap]; } } else if (sc.DateTimeOut[op] == sc.BaseDateTimeIn[as]) { // must be in first 5 seconds of new bar so // update prior bar with 5 second data oH[op] = max(H[as], oH[op]); oL[op] = min(L[as], oL[op]); oO[op] = O[as]; oC[op] = C[as]; oV[op] = V[as]; oT[op] = T[as]; } // then look at live data SCTimeAndSalesArray TSArray; sc.GetTimeAndSales(TSArray); int ts = TSArray.GetArraySize() - 1; if (ts >= 0 && TSArray[ts].Sequence > seqno) { int tp = ts, adjt = sc.TimeScaleAdjustment.GetTime(); double adj = sc.TimeScaleAdjustment; while (TSArray[tp].Sequence > seqno) {tp--;} // iterate through each time & sales value for ( ; tp <= ts; tp++) { if (tnsno == 0 && TSArray[tp].DateTime.GetTime() + adjt >= sc.DateTimeOut[os].GetTime() + sc.SecondsPerBar) { tnsno = 1; os++; sc.AddElements(1); sc.DateTimeOut[os].SetDate(sc.DateTimeOut[as].GetDate()); sc.DateTimeOut[os].SetTime(sc.DateTimeOut[as].GetTime() + sc.SecondsPerBar); oO[os] = oH[os] = oL[os] = oC[os] = TSArray[tp].Price; oV[os] = TSArray[tp].Volume; } else if (TSArray[tp].DateTime.GetTime() + adjt >= sc.DateTimeOut[os].GetTime()) { oH[os] = max(TSArray[tp].Price, oH[os]); if (TSArray[tp].Price > 0 && oL[os] > 0) oL[os] = min(TSArray[tp].Price, oL[os]); else oL[os] = max(TSArray[tp].Price, oL[os]); oC[os] = TSArray[tp].Price; oV[os] += TSArray[tp].Volume; } } seqno = TSArray[ts].Sequence; } sc.Subgraph[SC_HL][os] = (oH[os] + oL[os]) / 2; sc.Subgraph[SC_HLC][os] = (oH[os] + oL[os] + oC[os]) / 3; sc.Subgraph[SC_OHLC][os] = (oH[os] + oL[os] + oC[os] + oO[os]) / 4; sc.Subgraph[SC_HL][op] = (oH[op] + oL[op]) / 2; sc.Subgraph[SC_HLC][op] = (oH[op] + oL[op] + oC[op]) / 3; sc.Subgraph[SC_OHLC][op] = (oH[op] + oL[op] + oC[op] + oO[op]) / 4; } New DLL and cpp (code file): Date Time Of Last Edit: 2014-06-23 10:12:40
|
kiwi14.dll - Attached On 2014-06-23 05:52:08 UTC - Size: 158 KB - 675 views kiwi14.cpp - Attached On 2014-06-23 05:52:31 UTC - Size: 10.64 KB - 666 views |
[2014-06-23 17:32:37] |
xroads - Posts: 5 |
Kiwi, thank you for this.
|
[2014-06-24 00:58:03] |
Kiwi - Posts: 375 |
No problem Xroads ... I need it so I might as well share it. There is one issue I know of at present. IB can produce a spurious time and sales value "between sessions". In HSI this is a value at the beginning of lunchtime or in the few seconds before the new session starts. At present the solution is to press insert (rewrite chart) just after the new session starts which will rewrite the chart with no spurious bars present. I am testing a version where if a T&S bar is created and a 5 second bar is not received within the next 10 seconds the (now known to be) spurious bar will be removed. Similarly if the first 5 second bar of the session appears, needs to generate a new bar and the prior bar isn't based on 5 second data it will remove it. I need to test it for a while because "complex solutions" often reveal issues I hadn't previously thought of so I'll release a new version in the weekend if it works. In the mean time, if you notice a "wrong bar" (which will normally print a single price) or if you just want to be sure, just press Insert. Note: currently I increment volume if there is volume associated with the T&S values. I will stop that as it exposes you to rollover volume and other elements that might be filtered from the 5 second data feed. So in the next iteration volume will update only with the 5 second bars (much more accurate) unless someone objects here (please explain why). Date Time Of Last Edit: 2014-06-24 04:42:26
|
[2014-06-25 06:59:39] |
Kiwi - Posts: 375 |
All of those things improved the presentation. I also changed it so that the 5 second close can't ever set the close on the active bar - its always set by T&S. Why? Because I noted that as the new T&S based bar starts (first 5 seconds) you can get two 5 second bars and sometimes the close would swing wildly before the first 5 sec packet for the new bar arrived. Basically I think that one 5 sec bar and a T&S value (or 2) get out of sequence. When I eliminated the ability of that 5 second packet to reset the close the behaviour settles nicely and all the closes were orderly. So heres the new edition. /*==========================================================================*/
SCSFExport scsf_TrueLive_2014(SCStudyInterfaceRef sc) { SCFloatArray& O = sc.BaseDataIn[0], H = sc.BaseDataIn[1], L = sc.BaseDataIn[2], C = sc.BaseDataIn[3], V = sc.BaseDataIn[4], T = sc.BaseDataIn[5]; SCSubgraphRef oO = sc.Subgraph[0], oH = sc.Subgraph[1], oL = sc.Subgraph[2], oC = sc.Subgraph[3], oV = sc.Subgraph[4], oT = sc.Subgraph[5]; SCSubgraphRef o = sc.Subgraph[10], h = sc.Subgraph[11], l = sc.Subgraph[12], c = sc.Subgraph[13], v = sc.Subgraph[14], t = sc.Subgraph[15], o2 = sc.Subgraph[22], o3 = sc.Subgraph[23], o4 = sc.Subgraph[24], o5 = sc.Subgraph[25]; if (sc.SetDefaults) { sc.GraphName = "TrueLive 2014"; sc.StudyDescription = "True Live using Custom Chart 2014 Release"; sc.Subgraph[0].Name = "Open"; sc.Subgraph[1].Name = "High"; sc.Subgraph[2].Name = "Low"; sc.Subgraph[3].Name = "Last"; sc.Subgraph[4].Name = "Volume"; sc.Subgraph[5].Name = "# of Trades"; sc.Subgraph[6].Name = "HL"; sc.Subgraph[7].Name = "HLC"; sc.Subgraph[8].Name = "OHLC"; o2.Name="o2"; o3.Name="o3"; o4.Name="o4"; o5.Name="o5"; sc.GraphRegion = 0; // First region sc.GraphDrawType = GDT_CANDLESTICK; sc.DisplayAsMainPriceGraph=1; sc.IsCustomChart = 1; sc.UpdateAlways=1; sc.DrawZeros=0; return; } // sc.FreeDLL = 1; int as = sc.ArraySize-1; int ap = as - 1; int& seqno = sc.PersistVars->i1; int& tnsno = sc.PersistVars->i2; SCTimeAndSalesArray TSArray; sc.GetTimeAndSales(TSArray); int ts = TSArray.GetArraySize() - 1; if (sc.UpdateStartIndex == 0) { int os = 0; // os stores the position of the out array tnsno = seqno = 0; if (ts >= 0) seqno = TSArray[ts].Sequence; sc.ResizeArrays(0); for ( ; os < sc.ArraySize; os++) { sc.AddElements(1); sc.DateTimeOut[os] = sc.BaseDateTimeIn[os]; oO[os] = O[os]; oH[os] = H[os]; oL[os] = L[os]; oC[os] = C[os]; oV[os] = V[os]; oT[os] = T[os]; sc.Subgraph[SC_HL][os] = (oH[os] + oL[os]) / 2; sc.Subgraph[SC_HLC][os] = (oH[os] + oL[os] + oC[os]) / 3; sc.Subgraph[SC_OHLC][os] = (oH[os] + oL[os] + oC[os] + oO[os]) / 4; } } // First deal with underlying data int os = sc.OutArraySize-1; // add an extra bar if the underlying is later than the output bar if( sc.BaseDateTimeIn[as] > sc.DateTimeOut[os] ) { // only add element if there isn't a spurious t&s element present if(tnsno == 0) os++; sc.AddElements(1); sc.DateTimeOut[os] = sc.BaseDateTimeIn[as]; oO[os] = oH[os] = oL[os] = oC[os] = O[as]; } int op = os - 1; if (sc.DateTimeOut[os] == sc.BaseDateTimeIn[as]) { // Only apply 5 second data if its changed (ie dont reset live changes) if(c[os] != C[as] || v[os] != V[as] || h[os] != H[as] || l[os] != L[as]) { tnsno = 0; h[os] = H[as]; l[os] = L[as]; c[os] = C[as]; v[os] = V[as]; // update this bar oO[os] = O[as]; oH[os] = H[as]; oL[os] = L[as]; // oC[os] = C[as]; oV[os] = V[as]; oT[os] = T[as]; // match prior bar to 5 second data oO[op] = O[ap]; oH[op] = H[ap]; oL[op] = L[ap]; oC[op] = C[ap]; oV[op] = V[ap]; oT[op] = T[ap]; } } else if (sc.DateTimeOut[op] == sc.BaseDateTimeIn[as]) { // must be in first 5 seconds of new bar so // update prior bar with 5 second data oO[op] = O[as]; oH[op] = max(H[as], oH[op]); oL[op] = min(L[as], oL[op]); if (sc.CurrentSystemDateTime.GetTime() > sc.BaseDateTimeIn[as].GetTime() + sc.SecondsPerBar + 15) { oC[op] = C[as]; } oV[op] = V[as]; oT[op] = T[as]; } // then look at live data if (ts >= 0 && TSArray[ts].Sequence > seqno) { int tp = ts; int adjt = sc.TimeScaleAdjustment.GetTime(); double adj = sc.TimeScaleAdjustment; while (TSArray[tp].Sequence > seqno) {tp--;} // iterate through each time & sales value for ( ; tp <= ts; tp++) { // if its a new bar start one if (tnsno == 0 && TSArray[tp].DateTime.GetTime() + adjt >= sc.DateTimeOut[os].GetTime() + sc.SecondsPerBar) { tnsno = 1; // flag that a time&sales bar has been created os++; sc.AddElements(1); sc.DateTimeOut[os].SetDate(sc.DateTimeOut[as].GetDate()); sc.DateTimeOut[os].SetTime(sc.DateTimeOut[as].GetTime() + sc.SecondsPerBar); // note that for new session this bar time is wrong // and it will be cancelled as spurious so the new bar // will be formed when the first 5 sec bar arrives oO[os] = oH[os] = oL[os] = oC[os] = TSArray[tp].Price; oV[os] = TSArray[tp].Volume; } // else update high low and close for this bar else if (TSArray[tp].DateTime.GetTime() + adjt >= sc.DateTimeOut[os].GetTime() && TSArray[tp].DateTime.GetTime() + adjt < sc.DateTimeOut[os].GetTime() + sc.SecondsPerBar) { oH[os] = max(TSArray[tp].Price, oH[os]); if (TSArray[tp].Price > 0 && oL[os] > 0) oL[os] = min(TSArray[tp].Price, oL[os]); else oL[os] = max(TSArray[tp].Price, oL[os]); oC[os] = TSArray[tp].Price; } } seqno = TSArray[ts].Sequence; } // Check for spurious time & sales based bars (> 10 seconds with no 5sec) if(tnsno != 0) { // spurious if no 5 second confirmation within 15 seconds if(sc.CurrentSystemDateTime.GetDate() > sc.DateTimeOut[os].GetDate() || sc.CurrentSystemDateTime.GetTime() > sc.DateTimeOut[os].GetTime() + 15) { sc.AddElements(-1); tnsno = 0; } } sc.Subgraph[SC_HL][os] = (oH[os] + oL[os]) / 2; sc.Subgraph[SC_HLC][os] = (oH[os] + oL[os] + oC[os]) / 3; sc.Subgraph[SC_OHLC][os] = (oH[os] + oL[os] + oC[os] + oO[os]) / 4; sc.Subgraph[SC_HL][op] = (oH[op] + oL[op]) / 2; sc.Subgraph[SC_HLC][op] = (oH[op] + oL[op] + oC[op]) / 3; sc.Subgraph[SC_OHLC][op] = (oH[op] + oL[op] + oC[op] + oO[op]) / 4; } Date Time Of Last Edit: 2014-06-28 05:33:37
|
kiwi14.dll - Attached On 2014-06-25 06:56:53 UTC - Size: 157 KB - 540 views kiwi14.cpp - Attached On 2014-06-25 06:58:04 UTC - Size: 12.6 KB - 699 views kiwi14.dll - Attached On 2014-06-25 06:56:53 UTC - Size: 157 KB - 540 views kiwi14.cpp - Attached On 2014-06-25 06:58:04 UTC - Size: 12.6 KB - 699 views |
[2014-06-28 00:49:10] |
Kiwi - Posts: 375 |
Having run this version now for two days I'm happy that it provides a responsive accurate rendition of price so there isn't an update. In a fast market the first 5 second period after the last bar forms can result in a correction to the last close and this open but its seems to accurately reflect the best data that SC is receiving from IB. If anyone has issues then please post here. Good Trading. Date Time Of Last Edit: 2014-06-28 05:17:53
|
[2014-06-28 07:54:04] |
Sierra Chart Engineering - Posts: 104368 |
Is the source code posted in post #6, not the attached files, the latest code for True Live?
Sierra Chart Support - Engineering Level Your definitive source for support. Other responses are from users. Try to keep your questions brief and to the point. Be aware of support policy: https://www.sierrachart.com/index.php?l=PostingInformation.php#GeneralInformation For the most reliable, advanced, and zero cost futures order routing, *change* to the Teton service: Sierra Chart Teton Futures Order Routing |
[2014-06-29 03:46:56] |
Kiwi - Posts: 375 |
The code posted in 6 should match the "non-pvm" code from the cpp file attached for post 6. One difference might be that I replaced all the tabs with spaces after I first posted it because I had a mix of tabs and spaces which was confusing the board's formatting. If you were generalizing it you might want to use the price and volume format multipliers. I put them into the second (pvm) version of truelive but didn't really test them because I don't use them. TSArray[tp].Price * sc.RealTimePriceMultiplier; TSArray[tp].Volume * sc.MultiplierFromVolumeValueFormat(); Here's my copy of the cpp though. Date Time Of Last Edit: 2014-06-29 03:51:07
|
kiwi14.cpp - Attached On 2014-06-29 03:48:57 UTC - Size: 14.25 KB - 684 views |
[2014-06-30 02:44:49] |
Kiwi - Posts: 375 |
Engineering, I've been watching IB's version against this one and we're better ... they have the ability for a bar to be left diverged from the true data (not sure how). One issue I've found. If I delete and download the data I need to refresh the chart. Is there an acsil function that lets me know that data has been downloaded so that I can autorefresh the chart when that has happened? If there isn't an acsil member I'll just do it by forcing a recalc of the entire array if the newest time exceeds a most recently recorded bar time by more than 2 bar periods --- this works ok on my chart. Date Time Of Last Edit: 2014-06-30 04:01:33
|
[2014-06-30 04:47:42] |
Sierra Chart Engineering - Posts: 104368 |
We have included the latest True Live studies in the User Contributed Studies with Sierra Chart. In ACSIL there is this member: sc.DownloadingHistoricalData It is nonzero when data is being downloaded. There should be a recalculation of custom charts after a historical data download. But the way that works is kind of intricate . We would have to confirm that with code review. Sierra Chart Support - Engineering Level Your definitive source for support. Other responses are from users. Try to keep your questions brief and to the point. Be aware of support policy: https://www.sierrachart.com/index.php?l=PostingInformation.php#GeneralInformation For the most reliable, advanced, and zero cost futures order routing, *change* to the Teton service: Sierra Chart Teton Futures Order Routing |
[2014-06-30 05:43:44] |
Kiwi - Posts: 375 |
Thanks for that. To avoid the risk of getting it wrong I've just used a persistent variable to store "lasttime" that a bar was received. When you reload the data it picks up an earlier time which is more than 2 bars from the last bar of the reloaded data - this forces it to rebuild the chart so there is no possibility of a discontinutity. The changes are on the lines including the integer lasttime. If you don't change to this version you simply need to press insert to refresh the chart after you reload the data. /*==========================================================================*/
SCSFExport scsf_TrueLive_2014(SCStudyInterfaceRef sc) { SCFloatArray& O = sc.BaseDataIn[0], H = sc.BaseDataIn[1], L = sc.BaseDataIn[2], C = sc.BaseDataIn[3], V = sc.BaseDataIn[4], T = sc.BaseDataIn[5]; SCSubgraphRef oO = sc.Subgraph[0], oH = sc.Subgraph[1], oL = sc.Subgraph[2], oC = sc.Subgraph[3], oV = sc.Subgraph[4], oT = sc.Subgraph[5]; SCSubgraphRef o = sc.Subgraph[10], h = sc.Subgraph[11], l = sc.Subgraph[12], c = sc.Subgraph[13], v = sc.Subgraph[14], t = sc.Subgraph[15], o2 = sc.Subgraph[22], o3 = sc.Subgraph[23], o4 = sc.Subgraph[24], o5 = sc.Subgraph[25]; if (sc.SetDefaults) { sc.GraphName = "TrueLive 2014"; sc.StudyDescription = "True Live using Custom Chart 2014 Release"; sc.Subgraph[0].Name = "Open"; sc.Subgraph[1].Name = "High"; sc.Subgraph[2].Name = "Low"; sc.Subgraph[3].Name = "Last"; sc.Subgraph[4].Name = "Volume"; sc.Subgraph[5].Name = "# of Trades"; sc.Subgraph[6].Name = "HL"; sc.Subgraph[7].Name = "HLC"; sc.Subgraph[8].Name = "OHLC"; o2.Name="o2"; o3.Name="o3"; o4.Name="o4"; o5.Name="o5"; sc.GraphRegion = 0; // First region sc.GraphDrawType = GDT_CANDLESTICK; sc.DisplayAsMainPriceGraph=1; sc.IsCustomChart = 1; sc.UpdateAlways=1; sc.DrawZeros=0; return; } // sc.FreeDLL = 1; int as = sc.ArraySize-1; int ap = as - 1; int& seqno = sc.PersistVars->i1; int& tnsno = sc.PersistVars->i2; int& lasttime = sc.PersistVars->i10; SCTimeAndSalesArray TSArray; sc.GetTimeAndSales(TSArray); int ts = TSArray.GetArraySize() - 1; // lasttime is used to detect that data has been reloaded so // the chart needs to be refreshed if (sc.UpdateStartIndex == 0 || sc.BaseDateTimeIn[as].GetTime() > lasttime + sc.SecondsPerBar + sc.SecondsPerBar) { int os = 0; // os stores the position of the out array tnsno = seqno = 0; if (ts >= 0) seqno = TSArray[ts].Sequence; sc.ResizeArrays(0); for ( ; os < sc.ArraySize; os++) { sc.AddElements(1); sc.DateTimeOut[os] = sc.BaseDateTimeIn[os]; oO[os] = O[os]; oH[os] = H[os]; oL[os] = L[os]; oC[os] = C[os]; oV[os] = V[os]; oT[os] = T[os]; sc.Subgraph[SC_HL][os] = (oH[os] + oL[os]) / 2; sc.Subgraph[SC_HLC][os] = (oH[os] + oL[os] + oC[os]) / 3; sc.Subgraph[SC_OHLC][os] = (oH[os] + oL[os] + oC[os] + oO[os]) / 4; lasttime = sc.DateTimeOut[os].GetTime(); } } // First deal with underlying data int os = sc.OutArraySize-1; lasttime = sc.BaseDateTimeIn[as].GetTime(); // add an extra bar if the underlying is later than the output bar if( sc.BaseDateTimeIn[as] > sc.DateTimeOut[os] ) { // only add element if there isn't a spurious t&s element present if(tnsno == 0) os++; sc.AddElements(1); sc.DateTimeOut[os] = sc.BaseDateTimeIn[as]; oO[os] = oH[os] = oL[os] = oC[os] = O[as]; } int op = os - 1; if (sc.DateTimeOut[os] == sc.BaseDateTimeIn[as]) { // Only apply 5 second data if its changed (ie dont reset live changes) if(c[os] != C[as] || v[os] != V[as] || h[os] != H[as] || l[os] != L[as]) { tnsno = 0; h[os] = H[as]; l[os] = L[as]; c[os] = C[as]; v[os] = V[as]; // update this bar oO[os] = O[as]; oH[os] = H[as]; oL[os] = L[as]; // oC[os] = C[as]; oV[os] = V[as]; oT[os] = T[as]; // match prior bar to 5 second data oO[op] = O[ap]; oH[op] = H[ap]; oL[op] = L[ap]; oC[op] = C[ap]; oV[op] = V[ap]; oT[op] = T[ap]; } } else if (sc.DateTimeOut[op] == sc.BaseDateTimeIn[as]) { // must be in first 5 seconds of new bar so // update prior bar with 5 second data oO[op] = O[as]; oH[op] = max(H[as], oH[op]); oL[op] = min(L[as], oL[op]); if (sc.CurrentSystemDateTime.GetTime() > sc.BaseDateTimeIn[as].GetTime() + sc.SecondsPerBar + 15) { oC[op] = C[as]; } oV[op] = V[as]; oT[op] = T[as]; } // then look at live data if (ts >= 0 && TSArray[ts].Sequence > seqno) { int tp = ts; int adjt = sc.TimeScaleAdjustment.GetTime(); double adj = sc.TimeScaleAdjustment; while (TSArray[tp].Sequence > seqno) {tp--;} // iterate through each time & sales value for ( ; tp <= ts; tp++) { // if its a new bar start one if (tnsno == 0 && TSArray[tp].DateTime.GetTime() + adjt >= sc.DateTimeOut[os].GetTime() + sc.SecondsPerBar) { tnsno = 1; // flag that a time&sales bar has been created os++; sc.AddElements(1); sc.DateTimeOut[os].SetDate(sc.DateTimeOut[as].GetDate()); sc.DateTimeOut[os].SetTime(sc.DateTimeOut[as].GetTime() + sc.SecondsPerBar); // note that for new session this bar time is wrong // and it will be cancelled as spurious so the new bar // will be formed when the first 5 sec bar arrives oO[os] = oH[os] = oL[os] = oC[os] = TSArray[tp].Price; oV[os] = TSArray[tp].Volume; } // else update high low and close for this bar else if (TSArray[tp].DateTime.GetTime() + adjt >= sc.DateTimeOut[os].GetTime() && TSArray[tp].DateTime.GetTime() + adjt < sc.DateTimeOut[os].GetTime() + sc.SecondsPerBar) { oH[os] = max(TSArray[tp].Price, oH[os]); if (TSArray[tp].Price > 0 && oL[os] > 0) oL[os] = min(TSArray[tp].Price, oL[os]); else oL[os] = max(TSArray[tp].Price, oL[os]); oC[os] = TSArray[tp].Price; } } seqno = TSArray[ts].Sequence; } // Check for spurious time & sales based bars (> 10 seconds with no 5sec) if(tnsno != 0) { // spurious if no 5 second confirmation within 15 seconds if(sc.CurrentSystemDateTime.GetDate() > sc.DateTimeOut[os].GetDate() || sc.CurrentSystemDateTime.GetTime() > sc.DateTimeOut[os].GetTime() + 15) { sc.AddElements(-1); tnsno = 0; } } sc.Subgraph[SC_HL][os] = (oH[os] + oL[os]) / 2; sc.Subgraph[SC_HLC][os] = (oH[os] + oL[os] + oC[os]) / 3; sc.Subgraph[SC_OHLC][os] = (oH[os] + oL[os] + oC[os] + oO[os]) / 4; sc.Subgraph[SC_HL][op] = (oH[op] + oL[op]) / 2; sc.Subgraph[SC_HLC][op] = (oH[op] + oL[op] + oC[op]) / 3; sc.Subgraph[SC_OHLC][op] = (oH[op] + oL[op] + oC[op] + oO[op]) / 4; } Date Time Of Last Edit: 2014-06-30 05:47:08
|
kiwi14.cpp - Attached On 2014-06-30 05:45:46 UTC - Size: 15.89 KB - 676 views kiwi14.dll - Attached On 2014-06-30 05:46:31 UTC - Size: 160.5 KB - 638 views |
[2014-12-08 02:58:21] |
User148364 - Posts: 4 |
Hi Kiwi, thanks as always for providing this custom study to the community. I used to use TrueLive back with the -TD charts and it worked great. I'm giving SierraCharts another go, and I haven't been able to get this new TrueLive version to work. I followed all of your instructions, but after I add it to the chart, the last price box on the price axis stops moving (only moves after new bar creation, depending on bar period). If I add a time and sales study to the chart, I can see that the chart continues to receive time and sales data, but the study is not updating the bars at all. Are you still able to use this study? Any thoughts or suggestions? Thanks! Mike Date Time Of Last Edit: 2014-12-08 02:58:59
|
[2014-12-08 06:55:19] |
Kiwi - Posts: 375 |
Hi Mike, I just downloaded this dll myself. I checked that file data trade service settings >> record true real time was set to True. Then I opened EUR.USD-CASH-IDEALPRO.scid ... and checked that price only moved every 5 seconds but that the last price box was moving more often. Yep. Then added kiwi14's TrueLive 2014 and changed the colors to something darker so I could see it. And it worked .... the price box moved and the prices keep up with it. One thought ... what version of SC are you using. Perhaps (use EUR so I can do the same as you ... you could record exactly what you do and also what happens with a picture. Better thought (assuming study collections can be swapped between users still) ... here's my study collection with just that ... Also heres a picture with Eur 1m on Athens time ... http://i.imgur.com/Nlk26cm.png Also a pic of my ib settings just in case there's a clue ... http://i.imgur.com/lRiKzrZ.png Date Time Of Last Edit: 2014-12-08 06:59:24
|
JustTrueLive.StdyCollct - Attached On 2014-12-08 06:54:05 UTC - Size: 9.39 KB - 527 views |
[2014-12-08 12:46:00] |
User148364 - Posts: 4 |
Kiwi - Great news, I replicated your IB settings, tried it with EUR and it worked perfect. Then I loaded a CL chart and it also worked. Still didn't work on my HHI.HK chart, so I recreated the chart and then it seems to have started working. The settings I changed in IB were the intraday data storage time (was previously 1 tick) and the Clear Out of Order Market Depth Data, which may have been the culprit (although I can't say I understand what that setting does). I'm still not convinced HHI is working 100% yet, seems a little slow/behind/out of sync with IB's booktrader, but it's outside RTH so I will take another look tonight when the market is actually moving. Thanks again! Mike |
[2014-12-09 01:58:25] |
User148364 - Posts: 4 |
So after messing around quite a bit more, it seems the study is dependent on the data service time zone being set to Athens. When I have it set to my local time zone (US Central / Chicago) the study stops working and the charts freeze. Any idea why this would be? I don't see anything obvious in the code that would make this a requirement. Thanks again Kiwi. Mike |
[2014-12-17 00:49:57] |
Kiwi - Posts: 375 |
I'll have a think about that. Not sure why it should be as my time is set to brisbane, australia. Put your time for the market to 00:00 to 23:59 though ... just to make sure you aren't losing sight of your daily data ... also maybe set to allow data at all times not just RTH. Does that make a difference? |
[2014-12-17 05:02:21] |
User148364 - Posts: 4 |
I can give more details now that I've been using it for a few days. I'm in the US, central time zone, but I trade off IB's Hong Kong servers because I primarily trade Asian products in the US evening, so that's where the data is coming from. In the evening, to get TrueLive 2014 to work, I have to set my Data/Trade Service Settings time zone to a non-US based time zone (I'm currently using Hong Kong instead of Athens), otherwise the charts freeze and there's no movement. However, during the US daytime, to get Truelive to work, I have to change the time zone back to a US zone (i.e. Chicago). I haven't tried every time zone option during each period to isolate which ones work and which don't. I'm guessing throughout the day there's a moving line/zone that travels with the sun that if crossed over TrueLive stops working, but maybe there's just a hard cutoff based on a server reset time or something. Anyway, maybe that's a clue into this strange behavior. It works well enough for now, so I'm not worried about it, but at least the issue is repeatable so there has to be an explanation. Mike |
To post a message in this thread, you need to log in with your Sierra Chart account: