Forex Performance: SMA Crossover Pullback System

Before I head home to a galaxy far, far away for the holidays, I’ve summarized the SMA Crossover Pullback forex mechanical system results for the second half of 2015. Take a look!

SMA Crossover Pullback Profit/Loss
Period P/L in pips P/L in %
July 6-10 +900 +6.00
July 13-17 -132 -0.88
July 20-24 -182 -1.21
July 27-31 -159 -1.06
Aug 3-7 -63 -0.42
Aug 10-21 -300 -2.00
Aug 24-28 +95 +0.64
Aug 31-Sept 4 +300 +2.00
Sept 7-11 +209 +1.40
Sept 14-Oct 16* +371 +2.47
Oct 19-23* +335 +2.23
Oct 26-30* +300 +2.00
Nov 2-6* +73 +0.24
Nov 9-13* -153 -1.02
Nov 16-20* -120 -0.79
Nov 23-27* 0 0
Nov 30-Dec 4* +50 +0.33
Dec 7-11* +130  +0.86%
TOTAL +1,654 +10.79%

*With risk management tweaks

The forex mechanical system was off to a strong start in July, raking in 900 pips or 6% in gains in just one week. However, this was followed by a losing streak when ranging market conditions were in play. The positive run resumed towards the end of August and I’ve decided to make some risk management adjustments to allow the strategy to lock in profits along the way.

This led to an improved performance in Q4, as the forex system didn’t end up giving back all gains during a reversal, but got hit by a couple of weeks’ worth of sideways price action again.

All in all, the SMA Crossover Pullback mechanical system was able to chalk up a total of 1,654 pips or 10.79 % for the past six months. A few more positions were left open before I took off for my home planet so I’ll just tally those results up when I return to earth next year. Hey, even forex robots need to take vacations, too! See you in 2016!

  • cla

    Could you explain exit Rule if 150pips PT wasn’t reached?

    • In this scenario, a new crossover also gives an early exit signal.

  • I haven’t coded this system yet since I’m still checking if it’s consistently profitable. I’ll work on it, though!

  • Lee Spaziano

    I coded this system for TOS. Variable TimeFrame, SMA Lengths, Stops and Limits. This does an automatic back test for any chart. I cannot get good consistent profitable results. I would be happy to hand off the script to somebody else will to vet it.

    Perhaps there is a perfect SMA length, TF and stop to make this work. I hope so!

    • Cool beans! Have you tried optimizing using MT4? Mind sharing your script so I can tinker with some of the SMA, time frame, exits to see if we can get better parameters?

      • Lee Spaziano

        Sure. Email?

      • Lee Spaziano

        What is MT4?

      • Lee Spaziano

        I’ll try pasting the code in here. Keep in mind this code functions in ThinkScripts on Think Or Swim. Let me know if you need help installing it.

        I really would like to know if you have success with it. My success was very limited. Maybe you can tweak the parameters and make it in to a real winner.

        • I’m told that MT4 is the most common trading platform among human forex traders but I’ll give this Think or Swim a look. Thanks for the code!

      • Lee Spaziano

        input Full_Oscillate = no;
        input AllowMultiplePerCross = no;

        input Target_Ticks = 1000;
        input Stop_Ticks = 650;
        input SwitchToTrailingThreshhold_Ticks = 650;
        input TrailingStop_Ticks = 350;

        def price = FundamentalType.CLOSE;
        #input aggregationPeriod = AggregationPeriod.FIFTEEN_MIN;
        def aggregationPeriod = GetAggregationPeriod();
        input SMA_Shorter = 100;
        input SMA_Longer = 200;

        def StopLoss = Stop_Ticks * TickSize();
        def TP1 = Target_Ticks * TickSize();
        def SwitchToTrailingThreshhold = SwitchToTrailingThreshhold_Ticks * TickSize();
        def TrailingStop = TrailingStop_Ticks * TickSize();

        plot DailySMA_100;
        DailySMA_100 = Average(Fundamental(price, period = aggregationPeriod), SMA_Shorter);
        DailySMA_100.SetDefaultColor(CreateColor(255, 0, 0));
        DailySMA_100.SetPaintingStrategy(PaintingStrategy.LINE);

        plot DailySMA_200;
        DailySMA_200 = Average(Fundamental(price, period = aggregationPeriod), SMA_Longer);
        DailySMA_200.SetDefaultColor(CreateColor(0, 0, 255));
        DailySMA_200.SetPaintingStrategy(PaintingStrategy.LINE);

        # Look at the Stochastic
        input Stochastic_over_bought = 75;
        input Stochastic_over_sold = 25;
        def KPeriod = 10;
        def DPeriod = 10;
        def priceH = high;
        def priceL = low;
        def priceC = close;
        def averageType = AverageType.SIMPLE;

        def SlowK = reference StochasticFull(Stochastic_over_bought, Stochastic_over_sold, KPeriod, DPeriod, priceH, priceL, priceC, 3, if (averageType == 1) then AverageType.SIMPLE else AverageType.EXPONENTIAL).FullK;
        def SlowD = reference StochasticFull(Stochastic_over_bought, Stochastic_over_sold, KPeriod, DPeriod, priceH, priceL, priceC, 3, if (averageType == 1) then AverageType.SIMPLE else AverageType.EXPONENTIAL).FullD;

        def TrigOpen_L;
        def TrigClose_L;
        def IsOpen_L;
        def StopTarget_L;
        def TP1Target_L;
        def ClosedPrice_L;
        def TrigOpen_S;
        def TrigClose_S;
        def IsOpen_S;
        def StopTarget_S;
        def TP1Target_S;
        def ClosedPrice_S;

        def SMA_HasCrossed_L;
        def K_Went_OverBought_L;
        def D_Went_OverBought_L;
        def DK_Went_OverBought_L;
        def K_Went_OverSold_L;
        def D_Went_OverSold_L;
        def DK_Went_OverSold_L;
        def K_Not_OverSold_L;
        def D_Not_OverSold_L;
        def DK_Not_OverSold_L;
        def DK_Ascending_L;
        #def SMA_IsAscending = DailySMA_100 == Highest(DailySMA_100,3);
        def SMA_IsAscending = DailySMA_100 > DailySMA_200;
        def D_IsAscending = SlowD > SlowD[1];
        def K_IsAscending = SlowK > SlowK[1];

        def SMA_HasCrossed_S;
        def K_Went_OverBought_S;
        def D_Went_OverBought_S;
        def DK_Went_OverBought_S;
        def K_Went_OverSold_S;
        def D_Went_OverSold_S;
        def DK_Went_OverSold_S;
        def K_Not_OverBought_S;
        def D_Not_OverBought_S;
        def DK_Not_OverBought_S;
        def DK_Descending_S;
        #def SMA_IsDescending = DailySMA_100 == Lowest(DailySMA_100,3);
        def SMA_IsDescending = DailySMA_100 < DailySMA_200;
        def D_IsDescending = SlowD < SlowD[1];
        def K_IsDescending = SlowK = Stochastic_over_bought) then 1 else K_Went_OverBought_L[1] ;
        } else {
        K_Went_OverBought_L = 0;
        }

        if ( SMA_HasCrossed_S and !TrigClose_S[1] ) {
        K_Went_OverSold_S = if (SlowK = Stochastic_over_bought) then 1 else D_Went_OverBought_L[1] ;
        } else {
        D_Went_OverBought_L = 0;
        }

        if ( SMA_HasCrossed_S and !TrigClose_S[1] ) {
        D_Went_OverSold_S = if (SlowD <= Stochastic_over_sold) then 1 else D_Went_OverSold_S[1] ;
        } else {
        D_Went_OverSold_S = 0;
        }

        if (DoBothOverSoldAndOverBought) {
        if ( SMA_HasCrossed_L and D_Went_OverBought_L and K_Went_OverBought_L and !TrigClose_L[1] ) {
        DK_Went_OverBought_L = 1;
        } else {
        DK_Went_OverBought_L = 0;
        }
        } else {
        DK_Went_OverBought_L = if SMA_HasCrossed_L and !TrigClose_L[1] then 1 else 0;
        }

        if (DoBothOverSoldAndOverBought) {
        if ( SMA_HasCrossed_S and D_Went_OverSold_S and K_Went_OverSold_S and !TrigClose_S[1] ) {
        DK_Went_OverSold_S = 1;
        } else {
        DK_Went_OverSold_S = if SMA_HasCrossed_S and !TrigClose_S[1] then 1 else 0;
        }
        } else {
        DK_Went_OverSold_S = 1; #Skip this check
        }

        if ( SMA_HasCrossed_L and DK_Went_OverBought_L and !TrigClose_L[1] ) {
        K_Went_OverSold_L = if (SlowK = Stochastic_over_bought) then 1 else K_Went_OverBought_S[1] ;
        } else {
        K_Went_OverBought_S = 0;
        }

        if ( SMA_HasCrossed_L and DK_Went_OverBought_L and !TrigClose_L[1] ) {
        D_Went_OverSold_L = if (SlowD = Stochastic_over_bought) then 1 else D_Went_OverBought_S[1] ;
        } else {
        D_Went_OverBought_S = 0;
        }

        if ( SMA_HasCrossed_L and DK_Went_OverBought_L and K_Went_OverSold_L and D_Went_OverSold_L and !TrigClose_L[1] ) {
        DK_Went_OverSold_L = 1;
        } else {
        DK_Went_OverSold_L = 0;
        }

        if ( SMA_HasCrossed_S and DK_Went_OverSold_S and K_Went_OverBought_S and D_Went_OverBought_S and !TrigClose_S[1] ) {
        DK_Went_OverBought_S = 1;
        } else {
        DK_Went_OverBought_S = 0;
        }

        if ( SMA_HasCrossed_L and DK_Went_OverBought_L and DK_Went_OverSold_L and !TrigClose_L[1] ) {
        K_Not_OverSold_L = if (SlowK > Stochastic_over_sold) then 1 else K_Not_OverSold_L[1] ;
        } else {
        K_Not_OverSold_L = 0;
        }

        if ( SMA_HasCrossed_S and DK_Went_OverSold_S and DK_Went_OverBought_S and !TrigClose_S[1] ) {
        K_Not_OverBought_S = if (SlowK Stochastic_over_sold) then 1 else D_Not_OverSold_L[1] ;
        } else {
        D_Not_OverSold_L = 0;
        }

        if ( SMA_HasCrossed_S and DK_Went_OverSold_S and DK_Went_OverBought_S and !TrigClose_S[1] ) {
        D_Not_OverBought_S = if (SlowD > Stochastic_over_bought) then 1 else D_Not_OverBought_S[1] ;
        } else {
        D_Not_OverBought_S = 0;
        }

        if ( SMA_HasCrossed_L and DK_Went_OverBought_L and DK_Went_OverSold_L and K_Not_OverSold_L and D_Not_OverSold_L and !TrigClose_L[1] ) {
        DK_Not_OverSold_L = 1;
        } else {
        DK_Not_OverSold_L = 0;
        }

        if ( SMA_HasCrossed_S and DK_Went_OverSold_S and DK_Went_OverBought_S and K_Not_OverBought_S and D_Not_OverBought_S and !TrigClose_S[1] ) {
        DK_Not_OverBought_S = 1;
        } else {
        DK_Not_OverBought_S = 0;
        }

        if ( SMA_HasCrossed_L and DK_Went_OverBought_L and DK_Went_OverSold_L and DK_Not_OverSold_L and K_IsAscending and D_IsAscending and !TrigClose_L[1] ) {
        DK_Ascending_L = 1;
        } else {
        DK_Ascending_L = 0;
        }

        if ( SMA_HasCrossed_S and DK_Went_OverSold_S and DK_Went_OverBought_S and DK_Not_OverBought_S and K_IsDescending and D_IsDescending and !TrigClose_S[1] ) {
        DK_Descending_S = 1;
        } else {
        DK_Descending_S = 0;
        }

        #plot TempPlot = DK_Ascending_L;
        #TempPlot.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_UP);
        #TempPlot.AssignValueColor( CreateColor(0, 0, 192) );

        if IsOpen_L[1] and ( (low(priceType = “BID”) = TP1Target_L[1]) or TrigOpen_S[1]) {
        TrigClose_L = 1;
        if (low(priceType = “BID”) = TP1Target_L[1]) {
        ClosedPrice_L = TP1Target_L[1];
        } else {
        ClosedPrice_L = close(priceType = “ASK”);
        }
        }
        } else {
        TrigClose_L = 0;
        ClosedPrice_L = ClosedPrice_L[1];
        }

        if IsOpen_S[1] and ( (high(priceType = “ASK”) > StopTarget_S[1]) or (low(priceType = “ASK”) StopTarget_S[1]) {
        ClosedPrice_S = StopTarget_S[1];
        } else {
        if (low(priceType = “ASK”) <= TP1Target_S[1]) {
        ClosedPrice_S = TP1Target_S[1];
        } else {
        ClosedPrice_S = close(priceType = "BID");
        }
        }
        } else {
        TrigClose_S = 0;
        ClosedPrice_S = ClosedPrice_S[1];
        }

        if (IsOpen_L[1]) {
        TrigOpen_L = 0;
        } else {
        TrigOpen_L = if DK_Ascending_L then 1 else 0;
        }

        if (IsOpen_S[1]) {
        TrigOpen_S = 0;
        } else {
        TrigOpen_S = if DK_Descending_S then 1 else 0;
        }

        def StopDeltaDefault = StopLoss + TP1;

        if (TrigOpen_L) {
        IsOpen_L = 1;
        StopTarget_L = close – StopLoss ;
        TP1Target_L = close + TP1 ;
        } else {
        if(StopTarget_L[1] == 0) {
        StopTarget_L = close;
        } else {
        if (IsOpen_L) {
        if (TP1Target_L[1] – StopTarget_L[1]) StopTarget_L[1] then (high(priceType = “BID”) – TrailingStop) else StopTarget_L[1];
        } else {
        #Normal Mode
        if ( high(priceType = “BID”) > (StopTarget_L[1] + (SwitchToTrailingThreshhold + StopLoss)) ) {
        StopTarget_L = StopTarget_L[1] + TrailingStop;
        } else {
        StopTarget_L = StopTarget_L[1];
        }
        }
        } else {
        StopTarget_L = StopTarget_L[1];
        }
        }
        TP1Target_L = if TP1Target_L[1] == 0 then close else TP1Target_L[1];
        if (TrigClose_L) {
        IsOpen_L = 0;
        } else {
        IsOpen_L = IsOpen_L[1];
        }
        }

        if (TrigOpen_S) {
        IsOpen_S = 1;
        StopTarget_S = close + StopLoss ;
        TP1Target_S = close – TP1 ;
        } else {
        if(StopTarget_S[1] == 0) {
        StopTarget_S = close;
        } else {
        if (IsOpen_S) {
        if (StopTarget_S[1] – TP1Target_S[1]) < (StopDeltaDefault – (10* TickSize())) {
        #Trailing Mode
        StopTarget_S = if (low(priceType = "ASK") + TrailingStop) < StopTarget_S[1] then (low(priceType = "ASK") + TrailingStop) else StopTarget_S[1];
        } else {
        #Normal Mode
        if ( low(priceType = "ASK") < (StopTarget_S[1] – (SwitchToTrailingThreshhold + StopLoss)) ) {
        StopTarget_S = StopTarget_S[1] – TrailingStop;
        } else {
        StopTarget_S = StopTarget_S[1];
        }
        }
        } else {
        StopTarget_S = StopTarget_S[1];
        }
        }
        TP1Target_S = if TP1Target_S[1] == 0 then close else TP1Target_S[1];
        if (TrigClose_S) {
        IsOpen_S = 0;
        } else {
        IsOpen_S = IsOpen_S[1];
        }
        }

        plot TriggerOpen = if ( TrigOpen_L) then 1 else 0;
        TriggerOpen.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_UP);
        TriggerOpen.AssignValueColor( CreateColor(0, 192, 0) );

        plot TriggerOpen_S = if ( TrigOpen_S) then 1 else 0;
        TriggerOpen_S.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_DOWN);
        TriggerOpen_S.AssignValueColor( CreateColor(0, 192, 0) );

        plot TriggerClose = if ( TrigClose_L) then 1 else 0;
        TriggerClose.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_DOWN);
        TriggerClose.AssignValueColor( CreateColor(255, 0, 0) );

        plot TriggerClose_S = if ( TrigClose_S) then 1 else 0;
        TriggerClose_S.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_DOWN);
        TriggerClose_S.AssignValueColor( CreateColor(255, 0, 0) );

        def LongOpenCount = if TriggerOpen then LongOpenCount[1] + 1 else LongOpenCount[1];
        def MyLongOpenPrice = if TriggerOpen then close(priceType = "ASK") else MyLongOpenPrice[1];
        def LongTradeProfit = if TrigClose_L then ( ClosedPrice_L – MyLongOpenPrice) else 0;
        def RunningLongProfit = if (LongOpenCount == 0) then 0 else (if TrigClose_L then RunningLongProfit[1] + LongTradeProfit else RunningLongProfit[1]);

        def ShortOpenCount = if TriggerOpen_S then ShortOpenCount[1] + 1 else ShortOpenCount[1];
        def MyShortOpenPrice = if TriggerOpen_S then close(priceType = "BID") else MyShortOpenPrice[1];
        def ShortTradeProfit = if TrigClose_S then ( MyShortOpenPrice – ClosedPrice_S) else 0;
        def RunningShortProfit = if (ShortOpenCount == 0) then 0 else (if TrigClose_S then RunningShortProfit[1] + ShortTradeProfit else RunningShortProfit[1]);

        plot PlottedStop = if IsOpen_S then StopTarget_S else StopTarget_L;
        PlottedStop.AssignValueColor( if (IsOpen_L and IsOpen_L[1]) or (IsOpen_S and IsOpen_S[1]) then CreateColor(255, 0, 0) else CreateColor(255, 255, 255));

        plot PlottedTP = if IsOpen_S then TP1Target_S else TP1Target_L;
        PlottedTP.AssignValueColor( if (IsOpen_L and IsOpen_L[1]) or (IsOpen_S and IsOpen_S[1]) then CreateColor(0, 192, 0) else CreateColor(255, 255, 255));

        def TotalProfit = RunningLongProfit + RunningShortProfit;

        AddChartBubble(if TrigOpen_L then 1 else 0, close(priceType = "ASK") , "Buy Long " + close(priceType = "ASK"), CreateColor(192, 255, 192), 1);

        AddChartBubble(if TrigOpen_S then 1 else 0, close(priceType = "BID") , "Sell Short " + close(priceType = "BID"), CreateColor(192, 255, 192), 1);

        AddChartBubble(if TrigClose_L then 1 else 0, ClosedPrice_L, "Close Long " + ClosedPrice_L + " Profit " + LongTradeProfit , CreateColor(255, 192, 192), 0);

        AddChartBubble(if TrigClose_S then 1 else 0, ClosedPrice_S, "Close Short " + ClosedPrice_S + " Profit " + ShortTradeProfit, CreateColor(255, 192, 192), 0);

        AddChartBubble(IsNaN(close(period = aggregationPeriod)[-1]) , close, "Long Total " + RunningLongProfit + " Short Total " + RunningShortProfit + " Grand Total " + TotalProfit, CreateColor(210, 210, 210), 0);

        #Alert(IsNaN(close(period = aggregationPeriod)[-1]) and MyBuy , " SMA Crossover – Buy", Alert.ONCE, Sound.Bell);
        #Alert(IsNaN(close(period = aggregationPeriod)[-1]) and MySell , " SMA Crossover – Sell", Alert.ONCE, Sound.Bell);

      • Lee Spaziano

        Looks like it removed all my indentations, but Oh well.

  • Nick Latreille

    Hi Robopip,

    Could I email you a question I have about automating PipDaddy’s Daily Chart Art? I used your system to create a basic EA, but I don’t understand the code well enough to change RSI to stochastic. That would be a great help to me! Thanks!

    • Sure thing. I could forward it to him or try my best to answer it as well. I actually based the SMA parameters and stochastic confirmation from the Daily Chart Art framework. Mind if you share your code through email, too?

      • Nick Latreille

        Absolutely! Thank you for taking the time.

      • Nick Latreille

        Email sent to robopip.babypips@gmail.com. Thanks again!

        • Got it! I’ll look into this again and I’ll keep you posted. See you around!

  • jerry231

    Are you serious about learning the most profitable binary trade tactics
    ever? Do you still feel it is impossible to recover your lost funds
    from trading? contact me via jerry07lee@gmail.com . never has binary
    trade options been so rewarding