Description
ATTENTION, THIS CBOT IS NOT INTENDED TO BE USED AS-IS; IT IS A BETA TEST VERSION.
This robot demonstrates the use of a multisymbol robot with cTrader. It is intended for educational purposes.(Bugs possible) For use it take the indicator here : https://ctrader.com/algos/indicators/show/3757
Example of optimization for the dates from 14/10/2023 to 14/11/2023 on the EURUSD 1h. (+95% Without : monney management, correlation, symbol analysis etc…)
Contact me on Telegram for collaborative work: https://t.me/nimi012
// Version 1.0
using System;
using System.Linq;
using System.Threading;
using cAlgo.API;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
using cAlgo.Indicators;
using System.Collections.Generic;
using System.IO;
namespace cAlgo.Robots
{
//Set time zone to Eastern Standard Time EP9-Best time to trade
[Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class MultiSymbolTGR : Robot
{
//Create Parameters EP10-Functions and Parameters
[Parameter("Update Method", DefaultValue = UpdateMethodType.OnBar, Group = "============================================================================\nBASE SETTING\n============================================================================")]
public UpdateMethodType UpdateMethod { get; set; }
public enum UpdateMethodType
{
OnBar,
OnTick
}
[Parameter("Trade Start Hour", DefaultValue = 1, Group = "Open Management")]
public int StartHour { get; set; }
[Parameter("Trade End Hour", DefaultValue = 23, Group = "Open Management")]
public int EndHour { get; set; }
[Parameter("Symbol Selection Method", DefaultValue = SymbolSelectionMethodType.WatchList, Group = "Symbol Management")]
public SymbolSelectionMethodType SymbolSelectionMethod { get; set; }
public enum SymbolSelectionMethodType
{
CurrentChart,
SymbolList,
WatchList
}
[Parameter("Symbol List", DefaultValue = "USDHUF USDCZK NOKSEK NOKJPY EURZAR EURCZK USDPLN EURNOK USDSEK NZDCAD CHFJPY GBPJPY EURJPY NZDUSD GBPCHF GBPAUD EURCHF AUDCAD GBPUSD", Group = "Symbol Management")]
public string TradedSymbols { get; set; }
[Parameter("Watchlist Name", DefaultValue = "Good Spread", Group = "Symbol Management")]
public string WatchlistName { get; set; }
[Parameter("Fix Trade Amount", DefaultValue = false, Group = "============================================================================\nMONNEY MANAGEMENT\n============================================================================")]
public bool FixTradeAmount { get; set; }
[Parameter("Max Risk %", DefaultValue = 1.9, Group = "============================================================================\nMONNEY MANAGEMENT\n============================================================================")]
public double MaxRiskPct { get; set; }
[Parameter("Max Spread (in Pips)", DefaultValue = 3.1, MinValue = 0.1, Group = "============================================================================\nMONNEY MANAGEMENT\n============================================================================")]
public double MaxSpred { get; set; }
[Parameter("Min Bars after Close", DefaultValue = 21, Group = "============================================================================\nMONNEY MANAGEMENT\n============================================================================")]
public int MinBarsAfterClose { get; set; }
[Parameter("Martingale Mode", DefaultValue = MartingaleModeType.Standard, Group = "Martingale Management")]
public MartingaleModeType MartingaleMode { get; set; }
public enum MartingaleModeType
{
None,
Standard,
DrawDown
}
[Parameter("Martingale Increase Step", DefaultValue = 3, Group = "Martingale Management")]
public double MartingaleIncrease { get; set; }
[Parameter("Max Martingale Steps", DefaultValue = 2, Group = "Martingale Management")]
public int MartingaleMaxSteps { get; set; }
[Parameter("Martingale Break-Even ±Range [pips]", DefaultValue = 5, MinValue = 0.0, Group = "Martingale Management")]
public double MartingaleBreakevenRange { get; set; }
[Parameter("Pips Confirmation", DefaultValue = 1.2, Group = "============================================================================\nOPEN TYPE\n============================================================================")]
public double PipsConfirmation { get; set; }
[Parameter("Tp Factor", DefaultValue = 4, Group = "============================================================================\nOPEN TYPE\n============================================================================")]
public double TpFactor { get; set; }
[Parameter("TP Method", DefaultValue = TPMethodeType.None, Group = "Exit Management")]
public TPMethodeType TPMethode { get; set; }
public enum TPMethodeType
{
None
}
[Parameter("TSL on Start", DefaultValue = false, Group = "Exit")]
public bool TSLOnStart { get; set; }
[Parameter("Check on Tick", DefaultValue = false, Group = "Exit")]
public bool CheckOnTick { get; set; }
[Parameter("Level Buy", DefaultValue = 1, Group = "TGR")]
public double LevelBuy { get; set; }
[Parameter("Level Sell", DefaultValue = 88, Group = "TGR")]
public double LevelSell { get; set; }
[Parameter("Over Buy", DefaultValue = 110, Group = "TGR")]
public double OverBuy { get; set; }
[Parameter("Over Sell", DefaultValue = 5, Group = "TGR")]
public double OverSell { get; set; }
[Parameter("Over(Buy/Sell) In Look Back", DefaultValue = false, Group = "TGR")]
public bool InLookBack { get; set; }
[Parameter("Over(Buy/Sell) LookBack", DefaultValue = 150, Group = "TGR")]
public int OverBuySellLookBack { get; set; }
///////////////////////////////////////////////
[Parameter("Indicator Type", DefaultValue = ATGRBARSv3.EnumIndicatorType.Over_Buy_Sell, Group = " TGR Setting")]
public ATGRBARSv3.EnumIndicatorType IndicatorType { get; set; }
[Parameter("Initial Periods", DefaultValue = 17, Group = "Initialization")]
public int Periods { get; set; }
[Parameter("Sources Bars", DefaultValue = ATGRBARSv3.EnumSourcesBars.High_And_Low, Group = "Initialization")]
public ATGRBARSv3.EnumSourcesBars SourcesBars { get; set; }
[Parameter("Sources Over(Buy/Sell)", DefaultValue = ATGRBARSv3.EnumSourcesOverBuySell.Median_Price, Group = "Initialization")]
public ATGRBARSv3.EnumSourcesOverBuySell SourcesOverBuySell { get; set; }
[Parameter("Nbrs Indicator Load ", DefaultValue = 10, Group = "LoadCount")]
public int NbrsLoad { get; set; }
[Parameter("Periods Multiplicator ", DefaultValue = 1.418, Group = "LoadCount")]
public double PeriodsMultiTgr { get; set; }
[Parameter("Smooth Sensibility Over(Buy/Sell) ", DefaultValue = 2, Group = " Over(Buy/Sell")]
public int SensibilityOverBuySell { get; set; }
[Parameter("Smooth Result", DefaultValue = 13, Group = " Over(Buy/Sell")]
public int Smooth { get; set; }
[Parameter("Smooth Type", DefaultValue = MovingAverageType.Weighted, Group = " Over(Buy/Sell")]
public MovingAverageType SmoothType { get; set; }
[Parameter("Period Signal Result", DefaultValue = 34, Group = "Signal")]
public int PeriodSignalResult { get; set; }
[Parameter("MaType Signal Result", DefaultValue = MovingAverageType.Weighted, Group = "Signal")]
public MovingAverageType MaTypeSignalResult { get; set; }
[Parameter("Period Histo 1", DefaultValue = 2, Group = "Histogram")]
public int PeriodS1 { get; set; }
[Parameter("MaType Histo 1", DefaultValue = MovingAverageType.Exponential, Group = "Histogram")]
public MovingAverageType MaTypeS1 { get; set; }
[Parameter("Period Histo 2", DefaultValue = 114, Group = "Histogram")]
public int PeriodS2 { get; set; }
[Parameter("MaType Histo 2", DefaultValue = MovingAverageType.Weighted, Group = "Histogram")]
public MovingAverageType MaTypeS2 { get; set; }
//Create indicator variables EP5-ATR
private ATGRBARSv3[] tgr;
private AverageTrueRange[] atr;
private DonchianChannel[] dcn;
private string botName;
private double initialBalance;
private List<double>[] drawdown;
private Symbol[] TradeList;
private int barsBack;
private DateTime startTime;
private int[] lastLongCloseIndex;
private int[] lastShortCloseIndex;
private bool[] longSlLevelReached;
private bool[] shortSlLevelReached;
private int[] martingaleStep;
private double peak;
private DateTime[] LookBackOverBuy, LookBackOverSell;
protected override void OnStart()
{
if (SymbolSelectionMethod == SymbolSelectionMethodType.WatchList)
{
// Get the trade list from the watchlist provided by the user
foreach (Watchlist w in Watchlists)
{
if (w.Name == WatchlistName)
{
TradeList = Symbols.GetSymbols(w.SymbolNames.ToArray());
}
}
}
else if (SymbolSelectionMethod == SymbolSelectionMethodType.SymbolList)
{
// Get the trade list from the sysmbol list provided by the user
string[] SymbolList = TradedSymbols.Split(' ');
TradeList = Symbols.GetSymbols(SymbolList);
}
else
{
TradeList = new Symbol[1];
TradeList[0] = Symbol;
}
// Get all available symbols
//TradeList = new Symbol[Symbols.Count];
tgr = new ATGRBARSv3[TradeList.Length];
atr = new AverageTrueRange[TradeList.Length];
dcn = new DonchianChannel[TradeList.Length];
drawdown = new List<double>[TradeList.Length + 1].Select(item => new List<double>()).ToArray();
lastLongCloseIndex = new int[TradeList.Length];
lastShortCloseIndex = new int[TradeList.Length];
longSlLevelReached = new bool[TradeList.Length];
shortSlLevelReached = new bool[TradeList.Length];
martingaleStep = new int[TradeList.Length];
LookBackOverBuy = new DateTime[TradeList.Length];
LookBackOverSell = new DateTime[TradeList.Length];
// We subscribe to the bar event for each symbol for the current timeframe
Print("{0} traded symbols: ", TradeList.Length);
peak = Account.Balance;
int i = 0;
foreach (var symbol in TradeList)
{
Print(symbol.Name);
var bars = MarketData.GetBars(TimeFrame, symbol.Name);
if (UpdateMethod == UpdateMethodType.OnTick)
{
bars.Tick += OnBarTick;
barsBack = 0;
}
else if (UpdateMethod == UpdateMethodType.OnBar)
{
bars.BarOpened += OnBarOpened;
barsBack = 1;
if (CheckOnTick)
{
bars.Tick += OnBarTick;
}
}
//Load indicators on start up EP5-ATR
tgr[i] = Indicators.GetIndicator<ATGRBARSv3>(bars, IndicatorType, Periods, SourcesBars, SourcesOverBuySell, NbrsLoad, PeriodsMultiTgr, SensibilityOverBuySell, Smooth, SmoothType, PeriodSignalResult, MaTypeSignalResult, PeriodS1, MaTypeS1, PeriodS2, MaTypeS2,
0, 0, 0, false, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
Print(1);
atr[i] = Indicators.AverageTrueRange(bars, 150, MovingAverageType.Simple);
dcn[i] = Indicators.DonchianChannel(bars, 5);
drawdown[i].Add(0.0);
lastLongCloseIndex[i] = 0;
lastShortCloseIndex[i] = 0;
longSlLevelReached[i] = false;
shortSlLevelReached[i] = false;
martingaleStep[i] = 0;
LookBackOverBuy[i] = bars.OpenTimes.Last(150 + 2);
LookBackOverSell[i] = bars.OpenTimes.Last(150 + 2);
i++;
Print(symbol.CommissionType + " " + symbol.Commission);
}
drawdown[TradeList.Length].Add(0.0);
//subscribe to position close event - to move stoploss to Breakeven for the 2nd Trade
Positions.Closed += OnPositionClosed;
//Get Name of Bot and Currency pair of current instance EP15-Deploy
botName = GetType().ToString();
initialBalance = Account.Balance;
startTime = DateTime.Now;
}
private void OnBarTick(BarsTickEventArgs obj)
{
if (CheckTradeConditions(obj.Bars, botName) && UpdateMethod == UpdateMethodType.OnTick)
{
DoEntry(obj.Bars);
}
if (CheckExitConditions(obj.Bars, botName))
{
DoExit(obj.Bars);
}
}
private void OnBarOpened(BarOpenedEventArgs obj)
{
if (UpdateMethod == UpdateMethodType.OnBar)
{
if (CheckTradeConditions(obj.Bars, botName))
{
DoEntry(obj.Bars);
}
if (!CheckOnTick && CheckExitConditions(obj.Bars, botName))
{
DoExit(obj.Bars);
}
}
}
private void DoEntry(Bars bars)
{
if (Monitor.TryEnter(this))
{
try
{
int symbolIndex = Array.FindIndex(TradeList, x => x.Name == bars.SymbolName);
Symbol symbol = Array.Find(TradeList, x => x.Name == bars.SymbolName);
if (symbol != null)
{
// Put your core logic here EP7-MACD and EP8-Custom Indicators
var ClosePrice = bars.ClosePrices.Last(barsBack);
var PrevClosePrice = bars.ClosePrices.Last(barsBack + 1);
var Prev2ClosePrice = bars.ClosePrices.Last(barsBack + 2);
var LowPrice = bars.LowPrices.Last(barsBack);
var PrevLowPrice = bars.LowPrices.Last(barsBack + 1);
var HighPrice = bars.HighPrices.Last(barsBack);
var PrevHighPrice = bars.HighPrices.Last(barsBack + 1);
//Check for Entry Signal
{
var BuyTriggerR1 = tgr[symbolIndex].HistolUp.Last(0) > 0;
var SellTriggerS1 = tgr[symbolIndex].HistoDown.Last(0) < 0;
if (BuyTriggerR1)
{
Open(TradeType.Buy, bars, GetSl(bars, TradeType.Buy), (GetSl(bars, TradeType.Buy) * TpFactor), botName);
}
if (SellTriggerS1)
{
Open(TradeType.Sell, bars, GetSl(bars, TradeType.Sell), (GetSl(bars, TradeType.Sell) * TpFactor), botName);
}
}
}
}
finally
{
Monitor.Exit(this);
}
}
}
private void DoExit(Bars bars)
{
if (Monitor.TryEnter(this))
{
try
{
int symbolIndex = Array.FindIndex(TradeList, x => x.Name == bars.SymbolName);
Symbol symbol = TradeList[symbolIndex];
if (symbol != null)
{
var ClosePrice = bars.ClosePrices.Last(barsBack);
var LowPrice = bars.LowPrices.Last(barsBack);
var HighPrice = bars.HighPrices.Last(barsBack);
//Check for Exit Signal
}
}
finally
{
Monitor.Exit(this);
}
}
}
//Function after position is closed to move SL to Brakeven
private bool CheckTradeConditions(Bars bars, string Label)
{
//Check trade entry time (EP9-Best time to trade) and there's no existing position before entering a trade
int symbolIndex = Array.FindIndex(TradeList, x => x.Name == bars.SymbolName);
Symbol symbol = TradeList[symbolIndex];
return (Positions.FindAll(Label, symbol.Name).Length == 0 && PendingOrders.Where(x => x.Label == Label && x.SymbolName == symbol.Name).Count() == 0 && symbol.Spread < MaxSpred * symbol.PipSize && Server.Time.Hour >= StartHour && Server.Time.Hour < EndHour);
}
private bool CheckExitConditions(Bars bars, string Label)
{
//Check there's an existing position
return (Positions.FindAll(Label, bars.SymbolName).Length > 0 || PendingOrders.Where(x => x.Label == Label && x.SymbolName == bars.SymbolName).Count() > 0);
}
//Function for opening a new trade - EP10-Functions and Parameters
private void Open(TradeType TradeType, Bars bars, double? SLpips, double? TPpips, string Label)
{
int symbolIndex = Array.FindIndex(TradeList, x => x.Name == bars.SymbolName);
Symbol symbol = TradeList[symbolIndex];
if (Positions.FindAll(Label, symbol.Name, TradeType).Length == 0)
{
int index = bars.Count - 1;
if ((TradeType == TradeType.Buy && index - lastLongCloseIndex[symbolIndex] >= MinBarsAfterClose) || (TradeType == TradeType.Sell && index - lastShortCloseIndex[symbolIndex] >= MinBarsAfterClose))
{
//Calculate trade amount based on ATR - EP6-Money Management
TradeResult result;
var TradeAmount = ((FixTradeAmount ? initialBalance : Account.Equity) * MaxRiskPct) / (100.0 * (double)SLpips * symbol.PipValue);
if (Positions.FindAll(Label, symbol.Name, TradeType).Length == 0)
{
if (TPMethode == TPMethodeType.None)
{
TradeAmount = Symbol.NormalizeVolumeInUnits(TradeAmount * Math.Pow(MartingaleIncrease, martingaleStep[symbolIndex]), RoundingMode.Down);
result = ExecuteMarketOrder(TradeType, symbol.Name, TradeAmount, Label, SLpips, TPpips, null, TSLOnStart);
}
else
{
TradeAmount = Symbol.NormalizeVolumeInUnits(TradeAmount * Math.Pow(MartingaleIncrease, martingaleStep[symbolIndex]), RoundingMode.Down);
result = ExecuteMarketOrder(TradeType, symbol.Name, TradeAmount, Label, SLpips, null, null, TSLOnStart);
if (!result.IsSuccessful)
{
Print("Could not execute order: {0}", result.Error);
}
//result = ExecuteMarketOrder(TradeType, symbol.Name, TradeAmount, Label, SLpips, TPpips, null, TSLOnStart);
}
if (!result.IsSuccessful)
{
Print("Could not execute order: {0}", result.Error);
}
if (TradeType == TradeType.Buy)
{
longSlLevelReached[symbolIndex] = false;
}
else
{
shortSlLevelReached[symbolIndex] = false;
}
foreach (var position in Positions.FindAll(Label, symbol.Name, TradeType))
{
if (position.StopLoss == null)
{
Close(TradeType, bars.SymbolName, Label);
Print("No SL defined!");
break;
}
}
foreach (var order in PendingOrders.Where(x => x.Label == Label && x.SymbolName == symbol.Name && x.TradeType == TradeType))
{
if (order.StopLoss == null)
{
Close(TradeType, bars.SymbolName, Label);
Print("No SL defined!");
break;
}
}
}
}
}
}
//Function for closing trades - EP10-Functions and Parameters
private void Close(TradeType TradeType, string symbolName, string Label)
{
if (symbolName != "")
{
foreach (var position in Positions.FindAll(Label, symbolName, TradeType))
ClosePosition(position);
foreach (var order in PendingOrders.Where(x => x.Label == Label && x.SymbolName == symbolName && x.TradeType == TradeType))
CancelPendingOrder(order);
}
else
{
foreach (var symbol in TradeList)
{
foreach (var position in Positions.FindAll(Label, symbol.Name, TradeType))
ClosePosition(position);
foreach (var order in PendingOrders.Where(x => x.Label == Label && x.SymbolName == symbol.Name && x.TradeType == TradeType))
CancelPendingOrder(order);
}
}
}
protected override void OnStop()
{
var stopTime = DateTime.Now;
Print("Execution time: {0}", stopTime - startTime);
// Close all positions except in real-time (for better results in backtesting or optimization)
if (RunningMode != RunningMode.RealTime)
{
Close(TradeType.Buy, "", botName);
Close(TradeType.Sell, "", botName);
}
// Print more details of individual results per symbol
if ((RunningMode == RunningMode.SilentBacktesting || RunningMode == RunningMode.VisualBacktesting) && History.Count > 0)
{
double totalProfit = 0.0;
foreach (var sym in TradeList)
{
int lostBull = 0;
int lostBear = 0;
int wonBull = 0;
int wonBear = 0;
double wonPips = 0.0;
double lostPips = 0.0;
double profit = 0.0;
foreach (var hist in History.Where(x => x.Label == botName && x.SymbolName == sym.Name))
{
profit += hist.NetProfit;
if (hist.Pips >= 0)
{
wonPips += hist.Pips;
if (hist.TradeType == TradeType.Buy)
{
wonBull++;
}
else
{
wonBear++;
}
}
else
{
lostPips += hist.Pips;
if (hist.TradeType == TradeType.Buy)
{
lostBull++;
}
else
{
lostBear++;
}
}
}
Print("Symbol {0} results: {1} trades (+{2}, -{3} => {4}%), {5} net pips (+{6}, {7}), {8}{9} net profit with max {10}% balance drawdown", sym.Name, wonBull + lostBull + wonBear + lostBear, wonBull + wonBear, lostBull + lostBear, (100.0 * (wonBull + wonBear) / (wonBull + lostBull + wonBear + lostBear)).ToString("0.00"), (wonPips + lostPips).ToString("0.0"), wonPips.ToString("0.0"), lostPips.ToString("0.0"), profit.ToString("0.00"),
Account.Asset.Name, GetDrawDown(Array.FindIndex(TradeList, x => x.Name == sym.Name)).ToString("0.0"));
Print("{0} buy trades: {1} won, {2} lost => {3}%", wonBull + lostBull, wonBull, lostBull, (100.0 * wonBull / (wonBull + lostBull)).ToString("0.00"));
Print("{0} sell trades: {1} won, {2} lost => {3}%", wonBear + lostBear, wonBear, lostBear, (100.0 * wonBear / (wonBear + lostBear)).ToString("0.00"));
totalProfit += profit;
}
Print("Total net profit: {0}{1} = {2}% gain with max {3}% balance drawdown", totalProfit.ToString("0"), Account.Asset.Name, (100.0 * totalProfit / initialBalance).ToString("0"), GetDrawDown(TradeList.Length).ToString("0.0"));
Print("K-Ratio: " + GetKRatio().ToString("0.00"));
}
}
/////////////////////////////////////////////////////// On position Close + Management Martingale /////////////////////////////////////////////////////
private void OnPositionClosed(PositionClosedEventArgs args)
{
int symbolIndex = Array.FindIndex(TradeList, x => x.Name == args.Position.SymbolName);
if (args.Position.TradeType == TradeType.Buy)
{
lastLongCloseIndex[symbolIndex] = atr[symbolIndex].Result.Count + 1;
}
else if (args.Position.TradeType == TradeType.Sell)
{
lastShortCloseIndex[symbolIndex] = atr[symbolIndex].Result.Count + 1;
}
// Close(args.Position.TradeType, args.Position.SymbolName, args.Position.Label);
if (args.Position.Label == botName && args.Position.SymbolName == SymbolName)
{
if (MartingaleMode == MartingaleModeType.None)
{
martingaleStep[symbolIndex] = 0;
}
else if (MartingaleMode == MartingaleModeType.DrawDown)
{
double dd = GetDrawDown(symbolIndex);
if (dd > 0 && martingaleStep[symbolIndex] < MartingaleMaxSteps)
{
martingaleStep[symbolIndex]++;
}
else
{
martingaleStep[symbolIndex] = 0;
}
}
else if (MartingaleMode == MartingaleModeType.Standard)
{
if (args.Position.Pips < -MartingaleBreakevenRange && martingaleStep[symbolIndex] < MartingaleMaxSteps)
{
martingaleStep[symbolIndex]++;
}
else if (args.Position.Pips > MartingaleBreakevenRange || martingaleStep[symbolIndex] >= MartingaleMaxSteps)
{
martingaleStep[symbolIndex] = 0;
}
}
}
// Total Drawdown
CalcDrawDown(TradeList.Length, args.Position.NetProfit, History.Where(x => x.PositionId == args.Position.Id).First().Balance);
// Drawdown per Symbol
CalcDrawDown(Array.FindIndex(TradeList, x => x.Name == args.Position.SymbolName), args.Position.NetProfit, History.Where(x => x.PositionId == args.Position.Id).First().Balance);
}
//Martingal function
private void CalcDrawDown(int index, double gain, double balance)
{
drawdown[index].Add(drawdown[index][drawdown[index].Count - 1] + gain / balance * 100.0);
}
private double GetDrawDown(int index)
{
double maxDD = 0.0;
double dd = drawdown[index].Last();
double peak = drawdown[index].Max();
foreach (double c in drawdown[index])
{
peak = Math.Max(peak, dd);
maxDD = Math.Max(peak - dd, maxDD);
}
return maxDD;
}
//////////////////////////////////////////////////// Enter Special function /////////////////////////////////////////////////////////////
private DateTime GetOverBuy(Bars bars)
{
int symbolIndex = Array.FindIndex(TradeList, x => x.Name == bars.SymbolName);
Symbol symbol = TradeList[symbolIndex];
var prevOverBuy = bars.OpenTimes.Last(OverBuySellLookBack + 2);
for (int i = 3; i < OverBuySellLookBack; i++)
{
if ((tgr[symbolIndex].Result.Last(i) >= OverBuy) /*&& (prevResult < OverBuyEnterLevelEnter)*/)
{
prevOverBuy = bars.OpenTimes.Last(i);
LookBackOverBuy[symbolIndex] = LookBackOverBuy[symbolIndex] > prevOverBuy ? LookBackOverBuy[symbolIndex] : prevOverBuy;
}
}
return LookBackOverBuy[symbolIndex];
}
private DateTime GetOverSell(Bars bars)
{
int symbolIndex = Array.FindIndex(TradeList, x => x.Name == bars.SymbolName);
Symbol symbol = TradeList[symbolIndex];
var prevOverSell = bars.OpenTimes.Last(OverBuySellLookBack + 2);
for (int i = 3; i < OverBuySellLookBack; i++)
{
if (tgr[symbolIndex].Result.Last(i) <= OverSell)
{
prevOverSell = bars.OpenTimes.Last(i);
LookBackOverSell[symbolIndex] = LookBackOverSell[symbolIndex] > prevOverSell ? LookBackOverSell[symbolIndex] : prevOverSell;
}
}
return LookBackOverSell[symbolIndex];
}
private bool GetTooBigBar(Bars bars)
{
int symbolIndex = Array.FindIndex(TradeList, x => x.Name == bars.SymbolName);
Symbol symbol = TradeList[symbolIndex];
double atrSize = atr[symbolIndex].Result.Last(2) * 2;
double barSize = Math.Abs(Bars.OpenPrices.Last(1) - Bars.ClosePrices.Last(1));
bool result = false;
if (barSize < atrSize)
{
result = true;
}
else if (barSize >= atrSize)
{
result = false;
}
else
{
result = true;
}
return result;
}
private bool GetConfirmationEnterBarsBuy(Bars bars, TradeType tradeType)
{
int symbolIndex = Array.FindIndex(TradeList, x => x.Name == bars.SymbolName);
Symbol symbol = TradeList[symbolIndex];
var result = false;
if (tradeType == TradeType.Buy)
{
if (bars.ClosePrices.Last(1) > bars.OpenPrices.Last(1) && symbol.Bid > (bars.HighPrices.Last(1) + (PipsConfirmation / symbol.PipSize)))
{
result = true;
}
else if (bars.ClosePrices.Last(1) < bars.OpenPrices.Last(1) && symbol.Bid > (bars.OpenPrices.Last(1) + (PipsConfirmation / symbol.PipSize)))
{
result = true;
}
else
{
result = false;
}
}
if (tradeType == TradeType.Sell)
{
if (bars.ClosePrices.Last(1) > bars.OpenPrices.Last(1) && symbol.Ask < (bars.OpenPrices.Last(1) - (PipsConfirmation / symbol.PipSize)))
{
result = true;
}
else if (bars.ClosePrices.Last(1) < bars.OpenPrices.Last(1) && symbol.Ask < (bars.LowPrices.Last(1) - (PipsConfirmation / symbol.PipSize)))
{
result = true;
}
else
{
result = false;
}
}
return result;
}
/////////////////////////////////////////////////////////////////// monney management ////////////////////////////////////////////////////////////////
private double GetSl(Bars bars, TradeType tradeType)
{
int symbolIndex = Array.FindIndex(TradeList, x => x.Name == bars.SymbolName);
Symbol symbol = TradeList[symbolIndex];
if (tradeType == TradeType.Buy)
return (symbol.Ask - dcn[symbolIndex].Bottom.Last(0)) / symbol.PipSize;
else if (tradeType == TradeType.Sell)
return (dcn[symbolIndex].Top.Last(0) - symbol.Bid) / symbol.PipSize;
else
return 0;
}
private double GetTp(Bars bars, TradeType tradeType)
{
int symbolIndex = Array.FindIndex(TradeList, x => x.Name == bars.SymbolName);
Symbol symbol = TradeList[symbolIndex];
if (tradeType == TradeType.Buy)
return (symbol.Bid - dcn[symbolIndex].Bottom.Last(0)) / symbol.PipSize + symbol.Spread;
else if (tradeType == TradeType.Sell)
return (dcn[symbolIndex].Top.Last(0) - symbol.Ask) / symbol.PipSize + symbol.Spread;
else
return 0;
}
/////////////////////////////////////////////// Optimisation ////////////////////////////////////////////////////////////
private double GetKRatio()
{
double balance = initialBalance;
double log_balance = 0;
int size = History.Count + 1;
double[] log_profit = new double[size];
log_profit[0] = 0.0;
int count = 1;
double x_sum = 0;
double y_sum = 0;
foreach (var ticket in History)
{
log_balance += Math.Log((balance + ticket.NetProfit) / balance);
balance += ticket.NetProfit;
log_profit[count] = log_balance;
x_sum += count;
y_sum += log_balance;
count++;
}
double x_mean = x_sum / size;
double y_mean = y_sum / size;
double slope_numerator = 0;
double slope_denominator = 0;
double x_sqr = 0;
double y_sqr = 0;
for (int i = 0; i < size; i++)
{
slope_numerator += (i - x_mean) * (log_profit[i] - y_mean);
slope_denominator += Math.Pow(i - x_mean, 2);
y_sqr += Math.Pow(log_profit[i] - y_mean, 2);
x_sqr += Math.Pow(i - x_mean, 2);
}
double slope = slope_numerator / slope_denominator;
double std_err = Math.Sqrt((y_sqr - (Math.Pow(slope_numerator, 2) / x_sqr)) / ((size - 2) * x_sqr));
return slope / std_err;
}
protected override double GetFitness(GetFitnessArgs args)
{
return GetKRatio();
}
}
}
YE
YesOrNot
Joined on 10.10.2022 Blocked
- Distribution: Free
- Language: C#
- Trading platform: cTrader Automate
- File name: MultiSymbol TGR.algo
- Rating: 0
- Installs: 399
- Modified: 15/11/2023 17:43
Warning! Running cBots downloaded from this section may lead to financial losses. Use them at your own risk.
Note that publishing copyrighted material is strictly prohibited. If you believe there is copyrighted material in this section, please use the Copyright Infringement Notification form to submit a claim.
Comments
Log in to add a comment.
No comments found.