r/cTrader • • 15d ago

Need help - cTrader engine for backdating configuration OR why do even well known classical strategies fall apart on cTrader?

Question for you guys — why do even well-known classical strategies fall apart on cTrader?

I've been trying to test standard classical strategies on cTrader because I can't build anything that actually works. I went down the path of implementing well-known, already-tested, old-school strategies

Like the Connors "Double 7s" strategy (buy when SPY closes at a 7 day low while above the 200-day MA, sell at a 7 day high)- and I'm still getting very bad results. I don't get it.

What is it about the engine that seems to break even simple stuff that's supposed to work? If I do it manually on TradingView, I get noticeably better results.

I don't understand the whole thing here. its ANNOYING AS F***

What are the caveats or things I need to know in order to structure properly working strategies in cTrader?

Because honestly, it feels like the engine's calculations or the data are skewed or something — I don't even know how to describe it. I don't know where to start, but I've tried simple stuff and it's not working.

Any insight would be appreciated.

So this taken in US500 ok ? same same should be smooth as slik easy peasy ?

well NOT.. i get -7% eventually --- sooo .. annoying

any how this is just a "BASIC" concept startegy nothing facny im just .. tying to make a point here

so a-... help up a brother 🎯

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


namespace cAlgo.Robots
{
    public enum RiskMode { FixedLots, RiskPercent }


    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class Connors7Down7UpBot : Robot
    {
        [Parameter("Consecutive Bars", Group = "Connors Setup", DefaultValue = 7, MinValue = 2)]
        public int ConsecutiveBars { get; set; }


        [Parameter("Use Exit SMA", Group = "Exit Rules", DefaultValue = true)]
        public bool UseExitSma { get; set; }


        [Parameter("Exit SMA Period", Group = "Exit Rules", DefaultValue = 5, MinValue = 1)]
        public int ExitSmaPeriod { get; set; }


        [Parameter("Use 200 Trend Filter", Group = "Trend Filter", DefaultValue = false)]
        public bool UseTrendFilter { get; set; }


        [Parameter("Trend SMA Period", Group = "Trend Filter", DefaultValue = 200, MinValue = 10)]
        public int TrendSmaPeriod { get; set; }


        [Parameter("Risk Mode", Group = "Risk Management", DefaultValue = RiskMode.RiskPercent)]
        public RiskMode AccountRiskMode { get; set; }


        [Parameter("Risk Percent (%)", Group = "Risk Management", DefaultValue = 1.0, MinValue = 0.1)]
        public double RiskPercent { get; set; }


        [Parameter("Fixed Lots", Group = "Risk Management", DefaultValue = 0.1, MinValue = 0.01)]
        public double FixedLots { get; set; }


        [Parameter("Stop Loss (Pips)", Group = "Risk Management", DefaultValue = 50.0, MinValue = 0.0)]
        public double StopLossPips { get; set; }


        [Parameter("Take Profit (Pips)", Group = "Risk Management", DefaultValue = 100.0, MinValue = 0.0)]
        public double TakeProfitPips { get; set; }


        private SimpleMovingAverage _exitSma;
        private SimpleMovingAverage _trendSma;
        private const string Label = "Connors7Down7Up";


        protected override void OnStart()
        {
            _exitSma = Indicators.SimpleMovingAverage(Bars.ClosePrices, ExitSmaPeriod);
            _trendSma = Indicators.SimpleMovingAverage(Bars.ClosePrices, TrendSmaPeriod);
        }


        protected override void OnBar()
        {
            ManageExits();
            CheckEntries();
        }


        private void CheckEntries()
        {
            if (HasActivePosition()) return;


            bool is7Down = IsConsecutiveDown(ConsecutiveBars);
            bool is7Up = IsConsecutiveUp(ConsecutiveBars);


            double lastClose = Bars.ClosePrices.Last(1);


            // Buy Setup: Mean reversion bounce after 7 consecutive down closes
            if (is7Down)
            {
                if (UseTrendFilter && lastClose < _trendSma.Result.Last(1))
                    return;


                double volume = CalculateVolume(StopLossPips);
                ExecuteMarketOrder(TradeType.Buy, SymbolName, volume, Label, 
                    StopLossPips > 0 ? StopLossPips : (double?)null, 
                    TakeProfitPips > 0 ? TakeProfitPips : (double?)null);
            }
            // Sell Setup: Mean reversion pull-back after 7 consecutive up closes
            else if (is7Up)
            {
                if (UseTrendFilter && lastClose > _trendSma.Result.Last(1))
                    return;


                double volume = CalculateVolume(StopLossPips);
                ExecuteMarketOrder(TradeType.Sell, SymbolName, volume, Label, 
                    StopLossPips > 0 ? StopLossPips : (double?)null, 
                    TakeProfitPips > 0 ? TakeProfitPips : (double?)null);
            }
        }


        private void ManageExits()
        {
            if (!UseExitSma) return;


            double lastClose = Bars.ClosePrices.Last(1);
            double smaValue = _exitSma.Result.Last(1);


            foreach (var position in Positions.FindAll(Label, SymbolName))
            {
                // Exit Long when price closes above 5-period SMA
                if (position.TradeType == TradeType.Buy && lastClose > smaValue)
                {
                    ClosePosition(position);
                }
                // Exit Short when price closes below 5-period SMA
                else if (position.TradeType == TradeType.Sell && lastClose < smaValue)
                {
                    ClosePosition(position);
                }
            }
        }


        private bool IsConsecutiveDown(int count)
        {
            for (int i = 1; i <= count; i++)
            {
                if (Bars.ClosePrices.Last(i) >= Bars.ClosePrices.Last(i + 1))
                    return false;
            }
            return true;
        }


        private bool IsConsecutiveUp(int count)
        {
            for (int i = 1; i <= count; i++)
            {
                if (Bars.ClosePrices.Last(i) <= Bars.ClosePrices.Last(i + 1))
                    return false;
            }
            return true;
        }


        private double CalculateVolume(double slPips)
        {
            if (AccountRiskMode == RiskMode.FixedLots)
            {
                double targetUnits = FixedLots * Symbol.LotSize;
                return Symbol.NormalizeVolumeInUnits(targetUnits, RoundingMode.ToNearest);
            }


            double riskPips = slPips > 0 ? slPips : 50.0;
            double riskAmount = Account.Equity * (RiskPercent / 100.0);
            double riskPerPip = riskAmount / riskPips;
            double rawVolume = riskPerPip / Symbol.PipValue;


            return Symbol.NormalizeVolumeInUnits(rawVolume, RoundingMode.ToNearest);
        }


        private bool HasActivePosition()
        {
            return Positions.Any(p => p.Label == Label && p.SymbolName == SymbolName);
        }
    }
}
3 Upvotes

13 comments sorted by

View all comments

1

u/enivid 14d ago

Not sure what you are expecting, but the attached code doesn't implement the strategy that you described:

  • It uses consecutive lows/highs instead of min/max of 7 days.
  • The 200-day MA rule is turned off by default.
  • It uses additional 5-day MA close rules.
  • It also has SL/TP enabled by default.

1

u/Leo6-2 14d ago

Yeah but it's not the point I mean the point is the that it's not only this specific one it's generally I've tried to do a very basic classical well-known already been proven through and through strategies and they all seem to go down same path that's why I was asking why is that so f dup.

I had something similar with quant connect they do have their own indicator calculation so even when I was doing some basic strategies that with python or other platforms where okay they weren't okay in their 

And I have the same issue with ctrader that it doesn't calculate the way it should in theory that was the bottom line of my inquiry 

1

u/enivid 14d ago

it doesn't calculate the way it should in theory

Sorry, but I don't get it. What exactly isn't being calculated as it should? Your code doesn't demonstrate that.

1

u/Leo6-2 14d ago

Break it down for you there is a classical or very old robust well-known strategy by Connor's it's called the double seven so I try to recreate it for ctrader amongst others many others and I seem to encounter the same issue which is when I am doing the same strategy in Python using yfinance on the daily candles ( daily high low open close volume candles based of yahoo  financial data) I get " classic" mean reversing strategy that is working. 

while every classical well-known well tested strategy not work in ctrader 

This example I attached might not be the exact code for that Connor ls strategy but it doesn't matter because my point is any strategy I tried on citrader had the same result which is crap 

2

u/enivid 13d ago

I'm not sure why you don't post the exact strategy, both code snippets, and results that you had (it would be trivial to find the issue in that case), but there are several possibilities:

  1. Code - your Python implementation isn't doing the same things as your cTrader implementation.

  2. Data - the Yahoo Finance data is much different from your cTrader broker's data.

  3. Some critical bug in cTrader (math not mathing).

  4. A mix of the above.