Arg Posted November 16, 2021 Report Share Posted November 16, 2021 Hi, I have a simple script that I used elsewhere to find a spike in price/volume. I would like to use it here but need some assistance. There are two parts, first one for a spike in price, second part for a spike in volume. Both are identical in form. The final condition for the scan is to have true results for both the price and volume condition. The pseudocode is below. The ''def'' keyword is used to define a variable or a constant, and also a condition. c is the current price of the stock (not a 'closed' price - despite the name). c[1] is the closing value (price) of the last completed bar. c[2] is the closing value of the bar before c[1]. Same thing with volume v, v[1], v[2], v[3] etc. The stdev(closeLog, 11) calculates the standard deviation of 11 values of closeLog. So (if my understanding is correct) first value will be log(c[1] / c[2]), second value will be log(c[2] / c[3]), etc up to the final 11th value, which will be log(c[11] / c[12]). Any suggestions or help converting to a format suitable for the advanced scanner would be appreciated. ---------------------------------------------------------- def length = 11; def c = close; def closeLog = log(c[1] / c[2]); def SDevClose = stdev(closeLog, length) * sqrt(length / (length-1)); def m = SDevClose * c[1]; def pricespike = (c - c[1]) / m > 3; def v = volume; def volumeLog = log(v[1] / v[2]); def SDevVol = stdev(volumeLog, length) * sqrt(length / (length-1)); def n = SDevVol * v[1]; def volumespike = (v - v[1]) / n > 3; scan = pricespike and volumespike; ------------------------------------------------------------- Quote Link to comment Share on other sites More sharing options...
Mike Medved Posted November 16, 2021 Report Share Posted November 16, 2021 // note: everything after MainCalculation is basically state keeping mechanism public void MainCalculation() { DefinePaintbarParameter("Period","Period",true, 2, 100, 1, 11); var LogVal = Math.Log(Close[1]/Close[2]); CloseLog.Add(LogVal); var SDevClose = CloseLog.GetStDev() * Math.Sqrt(Period/(Period-1D)); var m = SDevClose * Close[1]; var pricespike = (Close-Close[1])/m > 3; LogVal = BarVolume[2]==0?0:Math.Log(BarVolume[1]/BarVolume[2]); VolLog.Add(LogVal); var SDevVol = VolLog.GetStDev() * Math.Sqrt(Period/(Period-1D)); var n = SDevVol * BarVolume[1]; var volumespike = n==0?false:((BarVolume-BarVolume[1])/m > 3); var scan = pricespike && volumespike; } int Period; StateFIFOQueue CloseLog; StateFIFOQueue VolLog; /// <summary> /// Is called at start of paintbar calculation, should be used to initialize anything needed for the paintbar /// </summary> private void PaintbarInitialize() { Period = Convert.ToInt32(GetPaintbarParameter("Period")); CloseLog = new StateFIFOQueue(Period); VolLog = new StateFIFOQueue(Period); } /// <summary> /// Holds paintbar state - fill with variables needed to be preserved for next paintbar calc /// </summary> private struct PaintbarState { } /// <summary> /// Holds current PB state - use to calc PB, changes to it carry over to next PB calc /// </summary> private PaintbarState CurrentState; /// <summary> /// Holds saved PB state - internal /// </summary> private PaintbarState SavedState; /// <summary> /// Is called at start of paintbar calculation, should be used to clear the paintbar state /// </summary> private void PaintbarClearState() { CurrentState = new PaintbarState(); CloseLog.ClearBoth(); VolLog.ClearBoth(); } /// <summary> /// Saves paintbar state (called internally). /// </summary> private void PaintbarSaveState() { SavedState = CurrentState; CloseLog.SaveState(); VolLog.SaveState(); } /// <summary> /// Restores paintbar state (called internally). /// </summary> private void PaintbarRestoreState() { CurrentState = SavedState; CloseLog.RestoreState(); VolLog.RestoreState(); } Quote Link to comment Share on other sites More sharing options...
Arg Posted November 16, 2021 Author Report Share Posted November 16, 2021 Wow...thanks a lot for this. Will try it out asap! Quote Link to comment Share on other sites More sharing options...
Arg Posted November 17, 2021 Author Report Share Posted November 17, 2021 (edited) How do I use this as a paintbar - my attempt below doesn't work. What am I doing wrong? var LogVal = Math.Log(Close[1]/Close[2]); CloseLog.Add(LogVal); var SDevClose = CloseLog.GetStDev() * Math.Sqrt(Period/(Period-1D)); var m = SDevClose * Close[1]; var pricespike = (Close-Close[1])/m > 3; LogVal = BarVolume[2]==0?0:Math.Log(BarVolume[1]/BarVolume[2]); VolLog.Add(LogVal); var SDevVol = VolLog.GetStDev() * Math.Sqrt(Period/(Period-1D)); var n = SDevVol * BarVolume[1]; var volumespike = n==0?false:((BarVolume-BarVolume[1])/n > 3); var scan = pricespike && volumespike && BarVolume[1]>15000; SetColorAndShape("spike", PBShape.ArrowUp_Hollow, SysColor.VolumeUp); TriggerAlert("spike"); SetScanResult(scan); Edited November 17, 2021 by Arg add code Quote Link to comment Share on other sites More sharing options...
Mike Medved Posted November 17, 2021 Report Share Posted November 17, 2021 Set scan result is ok - it would just show true or false. But the SetColorAndShape and TriggerAlert should probably be conditional on what scan is. That is, it should be if (scan) { SetColorAndShape... TriggerAlert... } Quote Link to comment Share on other sites More sharing options...
Arg Posted November 19, 2021 Author Report Share Posted November 19, 2021 Scan and paintbar are working. A few questions: 1) scan/paintbar doesn't seem to work in pre/post market. How do I fix this? 2) A scan trigger will fill in 2 columns in my portfolio: Scan Result column (with word "On") and ScanDT column with the time of the trigger. Both of these will disappear after a short time (probably to the next new bar?). Is there any way to find out the list of symbols that have been triggered? It would be useful if the Scan Result column could show a number indicating the number of bars elapsed since the last trigger. Or perhaps the ScanDT column could keep the trigger time shown permanently. Quote Link to comment Share on other sites More sharing options...
Mike Medved Posted November 19, 2021 Report Share Posted November 19, 2021 1. There is nothing in that code that detects if it is pre/postmarket. Maybe it is just that the conditions you're checking for do not occur in pre/post markets? 2. Arg, the way scans work - each iteration of the scan if SetScanResult is executed, that shows in the column. If it is NOT executed, nothing shows in the column. Which means that in your paintbar right now, if the condition is not true anymore, the scan result will blank out. Isn't that what you want? Quote Link to comment Share on other sites More sharing options...
Arg Posted November 21, 2021 Author Report Share Posted November 21, 2021 The code matches just about all hits during RTH (matching with other software). It doesn't pick up most of the pre/post market ones - perhaps there is some difference in input data during these times? Anyway, it is working well enough. One strange thing: setting Extended Hours to Always prevented any matches being shown (might be something in the code as I made another version which works ok on extended hours setting). The portfolio alert system doesn't seem to show the results for long enough. In order to see any matches I will need to keep my eyes on the portfolio all the time. The matches that appear in the Scan Result column are there for a very short time (seems to be much less than 1 minute). I would like an easy way to check to see what matches there have been - even if they were 5 minutes ago. The scan/watchlist on TOS provides this as it's possible to add code to provide a count back to the last trigger bar. The data can be sorted on this number to easily show the most recent matches. Quote Link to comment Share on other sites More sharing options...
Mike Medved Posted November 21, 2021 Report Share Posted November 21, 2021 1. If you have a version of paintbar where setting extended hours to Always prevent any of the matches from being shown - send it to me, tell me on what symbol to try it and I will look. 2. An easy way to see whether there were matches is to also do a TriggerAlert when the condition is satisfied (and fiddle with the alert notifications so that if it happens every second you don't get 100s of alerts). Then you can look at the Alert log. Quote Link to comment Share on other sites More sharing options...
Arg Posted November 21, 2021 Author Report Share Posted November 21, 2021 Attached paintbar MTspike shows fewer matches (over entire time period - including RTH) if extended hours is set to Always. I did a crude version which shows more hits. Any symbol can be used, eg BBIG, DIDI, etc MTspike.PBExport ArgSpike.PBExport Quote Link to comment Share on other sites More sharing options...
Mike Medved Posted November 22, 2021 Report Share Posted November 22, 2021 Thanks I will investigate. Quote Link to comment Share on other sites More sharing options...
Mike Medved Posted November 22, 2021 Report Share Posted November 22, 2021 Ok -- the line should be changed to: var LogValv = BarVolume[2]==0 && BarVolume[1]==0?0:Math.Log(BarVolume[1]/BarVolume[2]); because otherwise you get infinities. I also changed my code to remove such occurrences. Quote Link to comment Share on other sites More sharing options...
Arg Posted November 22, 2021 Author Report Share Posted November 22, 2021 Thanks. Alert notifications and Alert Log is working well to monitor the scan. Quote Link to comment Share on other sites More sharing options...
Vish Posted October 12 Report Share Posted October 12 (edited) Understand that you are trying to get PRICE/VOL spikes, did it help in catching them early? Edited October 12 by Vish Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.