Skip to content

Commit fd920f6

Browse files
authored
Merge pull request #3 from martcklm/o82xrr-codex/create-gold-trading-algo-bot-for-ctrader
Enhance XAUUSD bot
2 parents 581f67b + 52b2d99 commit fd920f6

File tree

2 files changed

+101
-2
lines changed

2 files changed

+101
-2
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,6 @@
11
# cTrader Algo API Samples
22
cBot / Indicator Samples of cTrader Algo API
3+
4+
## Custom Samples
5+
6+
- **GoldTrendStrategy**: Trend-following cBot for XAUUSD using Supertrend, MACD, RSI and optional dynamic volume management.

Robots/XAUUSD Trend Strategy/XAUUSD Trend Strategy/GoldTrendStrategy.cs

Lines changed: 97 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@
66
// profit of any kind. Use it at your own risk.
77
//
88
// -------------------------------------------------------------------------------------------------
9-
9+
using System;
10+
using cAlgo.API;
11+
using cAlgo.API.Indicators;
12+
using cAlgo.API.Internals;
1013
using cAlgo.API;
1114
using cAlgo.API.Indicators;
1215

@@ -19,7 +22,9 @@ public class GoldTrendStrategy : Robot
1922
private SimpleMovingAverage _fastMa;
2023
private SimpleMovingAverage _slowMa;
2124
private RelativeStrengthIndex _rsi;
22-
25+
private Supertrend _supertrend;
26+
private MacdCrossOver _macd;
27+
2328
[Parameter("Fast MA Source", Group = "Fast MA")]
2429
public DataSeries FastMaSource { get; set; }
2530

@@ -41,6 +46,36 @@ public class GoldTrendStrategy : Robot
4146
[Parameter("RSI Overbought", DefaultValue = 70, Group = "RSI", MinValue = 50, MaxValue = 100)]
4247
public int Overbought { get; set; }
4348

49+
[Parameter("Supertrend Periods", DefaultValue = 10, Group = "Supertrend", MinValue = 1)]
50+
public int SupertrendPeriods { get; set; }
51+
52+
[Parameter("Supertrend Multiplier", DefaultValue = 3.0, Group = "Supertrend", MinValue = 0.1)]
53+
public double SupertrendMultiplier { get; set; }
54+
55+
[Parameter("MACD Long Cycle", DefaultValue = 26, Group = "MACD", MinValue = 1)]
56+
public int MacdLongCycle { get; set; }
57+
58+
[Parameter("MACD Short Cycle", DefaultValue = 12, Group = "MACD", MinValue = 1)]
59+
public int MacdShortCycle { get; set; }
60+
61+
[Parameter("MACD Signal Periods", DefaultValue = 9, Group = "MACD", MinValue = 1)]
62+
public int MacdSignalPeriods { get; set; }
63+
64+
[Parameter("Volume (Lots)", DefaultValue = 0.01, Group = "Trade")]
65+
public double VolumeInLots { get; set; }
66+
67+
[Parameter("Use Dynamic Volume", DefaultValue = false, Group = "Trade")]
68+
public bool UseDynamicVolume { get; set; }
69+
70+
[Parameter("Risk Per Trade (%)", DefaultValue = 1.0, Group = "Trade", MinValue = 0.1)]
71+
public double RiskPercent { get; set; }
72+
73+
[Parameter("Max Spread (pips)", DefaultValue = 50, Group = "Trade", MinValue = 0)]
74+
public double MaxSpreadInPips { get; set; }
75+
76+
[Parameter("Trailing Stop (Pips)", DefaultValue = 50, Group = "Trade", MinValue = 0)]
77+
public double TrailingStopInPips { get; set; }
78+
4479
[Parameter("Volume (Lots)", DefaultValue = 0.01, Group = "Trade")]
4580
public double VolumeInLots { get; set; }
4681

@@ -58,6 +93,13 @@ protected override void OnStart()
5893
if (SymbolName != "XAUUSD")
5994
Print("Warning: This cBot is designed for XAUUSD. Current symbol is {0}.", SymbolName);
6095

96+
if (!UseDynamicVolume)
97+
_volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots);
98+
_fastMa = Indicators.SimpleMovingAverage(FastMaSource, FastMaPeriod);
99+
_slowMa = Indicators.SimpleMovingAverage(SlowMaSource, SlowMaPeriod);
100+
_rsi = Indicators.RelativeStrengthIndex(Bars.ClosePrices, RsiPeriod);
101+
_supertrend = Indicators.Supertrend(SupertrendPeriods, SupertrendMultiplier);
102+
_macd = Indicators.MacdCrossOver(Bars.ClosePrices, MacdLongCycle, MacdShortCycle, MacdSignalPeriods);
61103
_volumeInUnits = Symbol.QuantityToVolumeInUnits(VolumeInLots);
62104
_fastMa = Indicators.SimpleMovingAverage(FastMaSource, FastMaPeriod);
63105
_slowMa = Indicators.SimpleMovingAverage(SlowMaSource, SlowMaPeriod);
@@ -69,6 +111,59 @@ protected override void OnStart()
69111

70112
protected override void OnBarClosed()
71113
{
114+
var trendUp = _supertrend.UpTrend.Last(0) < Bars.LowPrices.Last(0) && _supertrend.DownTrend.Last(1) > Bars.HighPrices.Last(1);
115+
var trendDown = _supertrend.DownTrend.Last(0) > Bars.HighPrices.Last(0) && _supertrend.UpTrend.Last(1) < Bars.LowPrices.Last(1);
116+
117+
var macdCrossUp = _macd.MACD.Last(0) > _macd.Signal.Last(0) && _macd.MACD.Last(1) <= _macd.Signal.Last(1);
118+
var macdCrossDown = _macd.MACD.Last(0) < _macd.Signal.Last(0) && _macd.MACD.Last(1) >= _macd.Signal.Last(1);
119+
120+
if (Symbol.Spread / Symbol.PipSize > MaxSpreadInPips)
121+
return;
122+
123+
var volume = GetTradeVolume();
124+
125+
if (trendUp && macdCrossUp && _rsi.Result.LastValue < Oversold)
126+
{
127+
ClosePositions(TradeType.Sell);
128+
ExecuteMarketOrder(TradeType.Buy, SymbolName, volume, Label, StopLossInPips, TakeProfitInPips);
129+
}
130+
else if (trendDown && macdCrossDown && _rsi.Result.LastValue > Overbought)
131+
{
132+
ClosePositions(TradeType.Buy);
133+
ExecuteMarketOrder(TradeType.Sell, SymbolName, volume, Label, StopLossInPips, TakeProfitInPips);
134+
}
135+
}
136+
137+
protected override void OnTick()
138+
{
139+
foreach (var position in Positions.FindAll(Label))
140+
{
141+
double? newStopLoss;
142+
143+
if (position.TradeType == TradeType.Buy)
144+
newStopLoss = Symbol.Bid - TrailingStopInPips * Symbol.PipSize;
145+
else
146+
newStopLoss = Symbol.Ask + TrailingStopInPips * Symbol.PipSize;
147+
148+
if (position.TradeType == TradeType.Buy && (position.StopLoss == null || newStopLoss > position.StopLoss))
149+
ModifyPosition(position, newStopLoss, position.TakeProfit);
150+
else if (position.TradeType == TradeType.Sell && (position.StopLoss == null || newStopLoss < position.StopLoss))
151+
ModifyPosition(position, newStopLoss, position.TakeProfit);
152+
}
153+
}
154+
155+
private double GetTradeVolume()
156+
{
157+
if (!UseDynamicVolume)
158+
return _volumeInUnits;
159+
160+
var riskAmount = Account.Balance * RiskPercent / 100.0;
161+
var volumeInLots = riskAmount / (StopLossInPips * Symbol.PipValue);
162+
var units = Symbol.QuantityToVolumeInUnits(volumeInLots);
163+
units = Math.Max(Symbol.VolumeInUnitsMin, Math.Min(Symbol.VolumeInUnitsMax, units));
164+
return Symbol.NormalizeVolumeInUnits(units, RoundingMode.ToNearest);
165+
}
166+
72167
var inUptrend = _fastMa.Result.LastValue > _slowMa.Result.LastValue;
73168
var inDowntrend = _fastMa.Result.LastValue < _slowMa.Result.LastValue;
74169

0 commit comments

Comments
 (0)