// "First non-garbage strategy" (NGS) sclass NGSStrategy extends G22CandleBasedStrategy { settable double minDistance = 0.4; // input.float(0.4, minval=0, step=0.02) settable int period1 = 100; // the "slow" MA settable int period2 = 5; // the fast MA (for opening) settable double maMinMove = 0.07; // MA trend threshold settable double stopLoss = 2; settable double trailStart = 1; settable double trailPullback = 0.3; settable bool doLongs = true; settable bool doShorts = true; settable bool unblockAfterCrossingBand; settable bool unblockAfterTouchingBand = true; // per-run fields settable bool blockLong; settable bool blockShort; settable double maMove; void reset :: after { resetFields(this, "blockShort blockLong maMove"); } void unblockLong { if (blockLong) { log("Long unblock"); blockLong(false); } } void unblockShort { if (blockShort) { log("Short unblock"); blockShort(false); } } bool maRising() { ret maMove >= maMinMove; } bool maFalling() { ret maMove <= -maMinMove; } double upperBand() { ret ma1*(1+minDistance/100); } double lowerBand() { ret ma1*(1-minDistance/100); } ma1 = ta.sma(close, period1) ma2 = ta.sma(close, period2) maMove((ma1/ma1[1]-1)*100); longCondition(doLongs && ma2 > upperBand && maRising); shortCondition(doShorts & ma2 < lowerBand && maFalling); if (ma2 > ma1) unblockShort(); if (ma2 < ma1) unblockLong(); double drift = drift(); if (drift <= 0 && longCondition && !blockLong) { openLong(); blockLong(true); } if (drift >= 0 && shortCondition && !blockShort) { openShort(); blockShort(true); } if (drift > 0 && close < lowerBand) { closeAllPositions("Below band"); if (unblockAfterCrossingBand) unblockLong(); } if (drift < 0 && close > upperBand) { closeAllPositions("Above band"); if (unblockAfterCrossingBand) unblockShort(); } if (unblockAfterTouchingBand && close < upperBand) unblockLong(); if (unblockAfterTouchingBand && close > lowerBand) unblockShort(); } }