Creating signals that can be used by scanner

Shtick Hustler

Well-known member
Joined
Oct 15, 2020
Posts
106
Likes
46
I ran into this problem creating my Gaps study--signals worked, and signals showed up in the scanner criteria, but the scanner never found any hits.

I found the solution looking through the MW Study Source Code, specifically in the StochasticRSI.java code.

In my code I created the signals (note that this is Kotlin code, but should still be understandable):
Java:
desc.declareSignal(GapSignal.BULL_OPEN, get("LBL_BULL_GAP_OPEN"))
desc.declareSignal(GapSignal.BEAR_OPEN, get("LBL_BEAR_GAP_OPEN"))
desc.declareSignal(GapSignal.BULL_CLOSE, get("LBL_BULL_GAP_CLOSE"))
desc.declareSignal(GapSignal.BEAR_CLOSE, get("LBL_BEAR_GAP_CLOSE"))

Exported the signal values:
Java:
desc.exportValue(
    ValueDescriptor
        (GapSignal.BULL_OPEN, Enums.ValueType.BOOLEAN, get("LBL_BULL_GAP_OPEN"), null)
)
desc.exportValue(
    ValueDescriptor
        (GapSignal.BEAR_OPEN, Enums.ValueType.BOOLEAN, get("LBL_BEAR_GAP_OPEN"), null)
)
desc.exportValue(
    ValueDescriptor
        (GapSignal.BULL_CLOSE, Enums.ValueType.BOOLEAN, get("LBL_BULL_GAP_CLOSE"), null)
)
desc.exportValue(
    ValueDescriptor
        (GapSignal.BEAR_CLOSE, Enums.ValueType.BOOLEAN, get("LBL_BEAR_GAP_CLOSE"), null)
)

And, raised the signals in my code where appropriate:
Java:
ctx.signal(index, GapSignal.BULL_OPEN, "BULL open", low)

Signals were firing properly, but scanner wasn't picking them up.

On lines 194-195 of StochasticRSI I noticed these lines:
Java:
    boolean wasBuy = index == series.size()-1 && series.getBoolean(index, Signals.BUY, false);
    boolean wasSell = index == series.size()-1 && series.getBoolean(index, Signals.SELL, false);

    series.setBoolean(index, Signals.BUY, buy);
    series.setBoolean(index, Signals.SELL, sell);

It looked to me like the only purpose for creating the two boolean signal series was to set the 'wasBuy' and 'wasSell' vars.
But, for the hell of it, I decided to try it in my code and see what happened:
Java:
override fun calculate(index: Int, ctx: DataContext) {

    ...

    // set false initially
    //
    series.setBoolean(index, GapSignal.BULL_OPEN, false)
    series.setBoolean(index, GapSignal.BEAR_OPEN, false)
    series.setBoolean(index, GapSignal.BULL_CLOSE, false)
    series.setBoolean(index, GapSignal.BEAR_CLOSE, false)

    // set true on signal
    //
    when (signal) {
        GapSignal.BULL_OPEN -> {
            series.setBoolean(index, GapSignal.BULL_OPEN, true)
        }
        GapSignal.BEAR_OPEN -> {
            series.setBoolean(index, GapSignal.BEAR_OPEN, true)
        }
        GapSignal.BULL_CLOSE -> {
            series.setBoolean(index, GapSignal.BULL_CLOSE, true)
        }
        GapSignal.BEAR_CLOSE -> {
            series.setBoolean(index, GapSignal.BEAR_CLOSE, true)
        }
    }
    
    ...
    
}

I then re-tested the scanner, and...
it worked 🥳

So, it seems scanner needs not just signal values exported, but a history of those values saved in their own series.

If anyone else got their signals working with scanner and would like to confirm my findings, I'd appreciate it.
 
Last edited:

Spin

Well-known member
Joined
May 22, 2019
Posts
480
Likes
192
I dove in my archive (it has been a while that I coded scanner-related-functionality) and I think I can even raise you one:

I have a Study where I actually commented out the 'declareSignals'-lines, and only use the values written to DataSeries.
I think that is all the scanner needs, because
it works too 🥳

EDIT: I think the scanner simply 'looks back' the number of bars you ask it to, and checks on the DataSeries whether it finds the value you scan for. If it does, it will tell you, adding a 'weight' to show you how many bars ago it found that value.
 

Shtick Hustler

Well-known member
Joined
Oct 15, 2020
Posts
106
Likes
46
I have a Study where I actually commented out the 'declareSignals'-lines, and only use the values written to DataSeries.
I think that is all the scanner needs, because
it works too 🥳

Thanks for the confirmation.

I use both in Gaps.

Seems we're writing the MW dev manual post-by-post 😎
 
Top