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);
}
}
}