MA Cross doesn't cross consistently

Created at 26 Mar 2018, 10:50
How’s your experience with the cTrader Platform?
Your feedback is crucial to cTrader's development. Please take a few seconds to share your opinion and help us improve your trading experience. Thanks!
_I

_internet

Joined 19.03.2018

MA Cross doesn't cross consistently
26 Mar 2018, 10:50


Hi, 

 

I'm just wanting a piece of code that actually indicates/opens and closes a position each and every time on the first MA cross. So far, nothing I have tried has worked, not examples, not adapting the code, writing, none of it. I'm wondering if someone can show me how code for a consistent and reliable MA cross would look like. I've given an example of the types of order opening with what I'm currently trying where it opens or closes positions well away from the crosses and sometimes just changes. I've attached the source code, but am not sure how relevant it is as I'm really just looking for something that works. 

Help would be appreciated. Thank you.

using System;
using System.Linq;
using cAlgo.API;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
using cAlgo.Indicators;

namespace cAlgo
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class SampleTrendcBot : Robot
    {
        [Parameter("MA Type")]
        public MovingAverageType MAType { get; set; }

        [Parameter()]
        public DataSeries SourceSeries { get; set; }

        [Parameter("Slow Periods", DefaultValue = 10)]
        public int SlowPeriods { get; set; }

        [Parameter("Fast Periods", DefaultValue = 5)]
        public int FastPeriods { get; set; }

        [Parameter("Quantity (Lots)", DefaultValue = 1, MinValue = 0.01, Step = 0.01)]
        public double Quantity { get; set; }

        private MovingAverage slowMa;
        private MovingAverage fastMa;
        private const string label = "Sample Trend cBot";

        protected override void OnStart()
        {
            fastMa = Indicators.MovingAverage(SourceSeries, FastPeriods, MAType);
            slowMa = Indicators.MovingAverage(SourceSeries, SlowPeriods, MAType);
        }

        protected override void OnTick()
        {
            var longPosition = Positions.Find(label, Symbol, TradeType.Buy);
            var shortPosition = Positions.Find(label, Symbol, TradeType.Sell);

            var currentSlowMa = slowMa.Result.Last(0);
            var currentFastMa = fastMa.Result.Last(0);
            var previousSlowMa = slowMa.Result.Last(1);
            var previousFastMa = fastMa.Result.Last(1);

            if (previousSlowMa > previousFastMa && currentSlowMa <= currentFastMa && longPosition == null)
            {
                if (shortPosition != null)
                    ClosePosition(shortPosition);
                ExecuteMarketOrder(TradeType.Buy, Symbol, VolumeInUnits, label);
            }
            else if (previousSlowMa < previousFastMa && currentSlowMa >= currentFastMa && shortPosition == null)
            {
                if (longPosition != null)
                    ClosePosition(longPosition);
                ExecuteMarketOrder(TradeType.Sell, Symbol, VolumeInUnits, label);
            }
        }

        private long VolumeInUnits
        {
            get { return Symbol.QuantityToVolume(Quantity); }
        }
    }
}

 


@_internet
Replies

lec0456
26 Mar 2018, 11:10

Well, if I understand you correctly, to detect a cross, the official way is the following:

fastMA.Result.HasCrossedAbove(slowMA.Result, 1)

But you can always get false poitives.  in other words, it can cross and then cross back. 

So, its best to add some more criteria to the trade. Like the slope of the fast ma being above or below a certian thresh hold.

I tried out trading strategies based on ma crosses but never got very good results. Never the less, its a good place for beginers to start.

At one point I created an indicator that used the distance between the MAs before and after the cross and calculated a ratio.  I used that to give a weight to the strength of the cross.

If the cross was above a certain strength, it would execute the trade.

Also, trading crosses is a OnBar trading strategy, it does not work well OnTIck because during the course of a bar the MA can cross and cross back.  So, its a lagging indicator use have to atleast wait for the next bar to validate the cross and trigger the trade


@lec0456

_internet
28 Mar 2018, 11:15

Thanks that's great insight. Can I ask what you mean by official way? So if I used your way above, what would the program look like in terms of how it would change?

Didn't know that about OnBar, that makes a lot of sense. I'm wanting to open a position at the closing of the candle which registers the first MA cross. To your knowledge, would this work or would one need to wait to open a position at the open of the second candle after the MA cross is registered? 

Thank you


@_internet

lec0456
29 Mar 2018, 21:43

I say official because it is spotware's method to detect a cross.  Thier are other custom methods.  You just have to try it and see if it gives you the performance you are looking for. 

Here is what your code would look like. I would recomend just using the OnBar because if you want to make your decision to trade on the close of the previous bar, the open of the next bar is only one tick away.  Yes, there is a diference but 99.9% of the time these match up. If you want to get that specific then I would place the code back into the OnTick and calculate the time to close the candle.  So, if you were tradiing 15 min you would add a criteria Time_from_open.TotalMinutes>14 or doit in second if you want to get closer to the close.  But as far as I know, there is no event to trigger code on the close.  So, while you can get it close, you will never get it exact everytime.  

 

 protected override void OnBar()
        {
            var longPosition = Positions.Find(label, Symbol, TradeType.Buy);
            var shortPosition = Positions.Find(label, Symbol, TradeType.Sell);
 
            var currentSlowMa = slowMa.Result.Last(0);
            var currentFastMa = fastMa.Result.Last(0);
            var previousSlowMa = slowMa.Result.Last(1);
            var previousFastMa = fastMa.Result.Last(1);
 
            if (fastMA.Result.HasCrossedAbove(slowMA.Result,1) && longPosition == null)
            {
                if (shortPosition != null)
                    ClosePosition(shortPosition);
                ExecuteMarketOrder(TradeType.Buy, Symbol, VolumeInUnits, label);
            }
            else if (fastMA.Result.HasCrossedBelow(slowMA.Result,1) && shortPosition == null)
            {
                if (longPosition != null)
                    ClosePosition(longPosition);
                ExecuteMarketOrder(TradeType.Sell, Symbol, VolumeInUnits, label);
            }
        }
 
        private long VolumeInUnits
        {
            get { return Symbol.QuantityToVolume(Quantity); }
        }
    }

 


@lec0456

_internet
29 Mar 2018, 23:21

That's fantastic thank you very much for the code and the advice. I've been looking for that insight about how to best choose which point to open at - the close or the open of the next bar, and what's involved in making the decision. Really helps a lot.


@_internet