Jump to content
Medved Trader Forums

Help with price/volume spike scan


Recommended Posts

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;

-------------------------------------------------------------

 

Link to comment
Share on other sites

// 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();
}
Link to comment
Share on other sites

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 by Arg
add code
Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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?

 

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...