Description
This Cbot serves just as a sample on how to use my Data Extraction Class for Optimization Data Extraction and Backtesting Data Extraction.
You can refer for a accurate Explanation on how to properly use it in your cbot from this link CBot Data Extraction Class (Optimization & Backtesting Data Extractor).
This is a Cbot for demonstration purpose and doesn't guarantee any gaining, so don't use it on a live account with real money.
You can find me by joyining this Telegram Group http://t.me/cTraderCoders
Grupo de Telegram Para Brasileiros, Portugueses e todos aqueles que falam portugues:http://t.me/ComunidadeCtrader
Grupo CTrader en Español para Latinos: http://t.me/ComunidadCtrader
using System;
using System.Collections.Generic;
using cAlgo.API;
using cAlgo.API.Internals;
using cAlgo.API.Indicators;
using cAlgo.Indicators;
using System.Text;
using System.IO;
using System.Linq;
using System.Threading;
using System.Text.RegularExpressions;
namespace cAlgo.Robots
{
[Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.FullAccess)]
public class MACDBotExampleDataExtraction : Robot
{
[Parameter("Stop Loss", DefaultValue = 1.5)]
public double Stoploss { get; set; }
[Parameter("Take Profit", DefaultValue = 2.5)]
public double Takeprofit { get; set; }
[Parameter("Fast Period", DefaultValue = 12)]
public int Fastperiod { get; set; }
[Parameter("Fast Period", DefaultValue = 26)]
public int Slowperiod { get; set; }
[Parameter("Signal Period", DefaultValue = 9)]
public int Signalperiod { get; set; }
[Parameter("Account % risk ", DefaultValue = 1)]
public double AccountPct { get; set; }
[Parameter("ATR Multiplier ", DefaultValue = 1.5)]
public double AtrMultiplier { get; set; }
[Parameter("Optimization File Name", DefaultValue = "CSV_OptimizationDataFile")]
public string OptimizationFileName { get; set; }
[Parameter("Optimization File Name", DefaultValue = "CSV_BackestingDataFile")]
public string BacktestingFileName { get; set; }
[Parameter("Enable Data Extraction", DefaultValue = true)]
public bool DataWrittingEnabled { get; set; }
public Mutex mutex = new Mutex(false, @"Global\mutex2203");
public CBotPerformanceDataExtractor Extractor;
private AverageTrueRange atr;
private MacdCrossOver macd;
protected override void OnStart()
{
atr = Indicators.AverageTrueRange(14, MovingAverageType.Exponential);
macd = Indicators.MacdCrossOver(Slowperiod, Fastperiod, Signalperiod);
//List<string> ParametersName = new List<string> {}; // uncomment this line if you want this data empty
List<string> ParametersName = new List<string> { "Take Profit", "Stop Loss", "Account Risk %" };
//List<string> ParametersValue = new List<string> { }; // uncomment this line if you want this data empty
List<string> ParametersValue = new List<string> { Takeprofit.ToString(), Stoploss.ToString(), AccountPct.ToString() };
Extractor = new CBotPerformanceDataExtractor();
Extractor.InitOptimization(this, OptimizationFileName, ParametersName, ParametersValue);
if (RunningMode == RunningMode.SilentBacktesting || RunningMode == RunningMode.VisualBacktesting)
{
Extractor.InitBacktesting(this, BacktestingFileName);
}
if (RunningMode == RunningMode.Optimization && DataWrittingEnabled)
{
try
{
mutex.WaitOne();
Extractor.CreateOptimizationDataFile();
}
finally
{
mutex.ReleaseMutex();
}
}
}
protected override void OnTick()
{
if (RunningMode == RunningMode.Optimization && DataWrittingEnabled)
{
Extractor.GetTradeDrawDownData();
}
if (RunningMode == RunningMode.SilentBacktesting || RunningMode == RunningMode.VisualBacktesting && DataWrittingEnabled)
{
Extractor.GetTradeDrawDownData();
}
}
protected override void OnStop()
{
if (RunningMode == RunningMode.Optimization && DataWrittingEnabled)
{
try
{
mutex.WaitOne();
Extractor.WriteOptimizationResult();
}
finally
{
mutex.ReleaseMutex();
}
}
if (RunningMode == RunningMode.SilentBacktesting || RunningMode == RunningMode.VisualBacktesting && DataWrittingEnabled)
{
Extractor.WriteBacktestingResult();
}
}
protected override void OnBar()
{
var PrevATR = Math.Round(atr.Result.Last(1) / Symbol.PipSize);
var PositionSize = (Account.Equity * (AccountPct * 0.01)) / (AtrMultiplier * PrevATR * Symbol.PipValue);
PositionSize = Symbol.NormalizeVolumeInUnits(PositionSize, RoundingMode.Down);
if (macd.MACD.Last(1) > macd.Signal.Last(1) & macd.MACD.Last(2) < macd.Signal.Last(2) & macd.MACD.Last(1) > 0 & macd.Signal.Last(1) > 0)
{
ExecuteMarketOrder(TradeType.Buy, SymbolName, PositionSize, "MACD", Stoploss * PrevATR, Takeprofit * PrevATR);
}
else if (macd.MACD.Last(1) < macd.Signal.Last(1) & macd.MACD.Last(2) > macd.Signal.Last(2) & macd.MACD.Last(1) < 0 & macd.Signal.Last(1) < 0)
{
ExecuteMarketOrder(TradeType.Sell, SymbolName, PositionSize, "MACD", Stoploss * PrevATR, Takeprofit * PrevATR);
}
}
}
public class CBotPerformanceDataExtractor : Robot
{
private Robot Bot;
private string CurrencyName;
public int OptimizationPassId;
public string FullPath;
public string Filename;
public string header;
public List<string> parametersValue;
public int TradeNumber;
public double EquityResult;
public double BalanceResult;
public double NetProfitResult;
public int TradesResult;
public int WinningTradesResult;
public int LosingTradesResult;
public double ProfitFactorResult;
public double SharpeRatioResult;
public double SortinoRatioResult;
public double AverageTradeResult;
private double MaxBalance = 0.0;
private double MaxBalanceDrawDownPct = 0.0;
private double MaxBalanceDrawDown = 0.0;
private double MaxEquity = 0.0;
private double MaxEquityDrawDownPct = 0.0;
private double MaxEquityDrawDown = 0.0;
private string SymbolTimeFrame;
public static Dictionary<string, string> Currencies = new Dictionary<string, string> {
{"AUD", "$"}, {"CHF", "fr."},{"EUR", "€"},{"GBP", "£"}, {"HKD", "HK$"}, {"NZD", "$"}, {"SEK","kr"},{"USD","$"},
{"ZAR","R"},{"CAD","$"},{"CNY","¥"},{"MXN","$"},{"SGD","$"},{"JPY","¥"}};
public void InitOptimization(Robot bot, string filename, List<string> parametersname, List<string> pvals)
{
Bot = bot;
SetSymbolTimeFrame();
parametersValue = pvals;
FullPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "\\" + filename + ".csv";
if (Currencies.ContainsKey(Bot.Account.Asset.Name))
{
string val = Currencies[Bot.Account.Asset.Name];
CurrencyName = val;
}
else
CurrencyName = Bot.Account.Asset.Name;
header = "Optimization Pass,Symbol TimeFrame,Equity,Balance,Netprofit,Trades,Winning Trades,Losing Trades,Profit Factor,Max Equity DD (%),Max Balance DD (%),";
header += string.Format("Max Equity DD ({0}),Max Balance DD ({1}),Sharpe,Sortino,Average Trade", CurrencyName, CurrencyName);
bool isEmpty = !parametersname.Any();
if (!isEmpty)
{
var result = "," + string.Join(",", parametersname.Select(s => $"{s}"));
header += result;
}
}
public void InitBacktesting(Robot bot, string filename)
{
Bot = bot;
FullPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "\\" + filename + ".csv";
header = "Summary,All Trades,Long Trades,Short Trades";
File.AppendAllText(FullPath, header + Environment.NewLine, Encoding.UTF8);
}
public void WriteBacktestingResult()
{
var NetProfitTrades = GetNetProfit(Bot.History.Select(trade => trade.NetProfit));
var NetProfitLong = GetNetProfit(Bot.History.Where(x => x.TradeType == TradeType.Buy).Select(trade => trade.NetProfit));
var NetProfitShort = GetNetProfit(Bot.History.Where(x => x.TradeType == TradeType.Sell).Select(trade => trade.NetProfit));
var backtestinresult = string.Format("Net Profit,{0},{1},{2}\n", NetProfitTrades, NetProfitLong, NetProfitShort);
var ProfitFactorTrades = GetProfitFactor(Bot.History.Select(trade => trade.NetProfit));
var ProfitFactorLong = GetProfitFactor(Bot.History.Where(x => x.TradeType == TradeType.Buy).Select(trade => trade.NetProfit));
var ProfitFactorShort = GetProfitFactor(Bot.History.Where(x => x.TradeType == TradeType.Sell).Select(trade => trade.NetProfit));
backtestinresult += string.Format("Profit Factor,{0},{1},{2}\n", ProfitFactorTrades, ProfitFactorLong, ProfitFactorShort);
var CommissionsTrades = GetCommissions(Bot.History.Select(trade => trade.Commissions));
var CommissionsLong = GetCommissions(Bot.History.Where(x => x.TradeType == TradeType.Buy).Select(trade => trade.Commissions));
var CommissionsShort = GetCommissions(Bot.History.Where(x => x.TradeType == TradeType.Sell).Select(trade => trade.Commissions));
backtestinresult += string.Format("Commission,{0},{1},{2}\n", CommissionsTrades, CommissionsLong, CommissionsShort);
backtestinresult += string.Format("Max Balance Draw Down %,{0},{1},{2}\n", MaxBalanceDrawDownPct, "-", "-");
backtestinresult += string.Format("Max Equity Draw Down %,{0},{1},{2}\n", MaxEquityDrawDownPct, "-", "-");
var TotalTrades = GetTrades(Bot.History.Select(trade => trade.NetProfit));
var TotalTradesLong = GetTrades(Bot.History.Where(x => x.TradeType == TradeType.Buy).Select(trade => trade.NetProfit));
var TotalTradesShort = GetTrades(Bot.History.Where(x => x.TradeType == TradeType.Sell).Select(trade => trade.NetProfit));
backtestinresult += string.Format("Total Trades,{0},{1},{2}\n", TotalTrades, TotalTradesLong, TotalTradesShort);
var totalWinningTrades = GetWiningTrades(Bot.History.Select(trade => trade.NetProfit));
var longWinningTrades = GetWiningTrades(Bot.History.Where(x => x.TradeType == TradeType.Buy).Select(trade => trade.NetProfit));
var shorWinningTrades = GetWiningTrades(Bot.History.Where(x => x.TradeType == TradeType.Sell).Select(trade => trade.NetProfit));
backtestinresult += string.Format("Winning Trades,{0},{1},{2}\n", totalWinningTrades, longWinningTrades, shorWinningTrades);
var MaxConsWinTrades = MaxConsecutiveWin("Trades");
var MaxConsWinLongTrades = MaxConsecutiveWin("Long");
var MaxConsWinShortTrades = MaxConsecutiveWin("Short");
backtestinresult += string.Format("Max Consecutive Winning Trades,{0},{1},{2}\n", MaxConsWinTrades, MaxConsWinLongTrades, MaxConsWinShortTrades);
var largestWinningTrade = LargesWiningTrade(Bot.History.Select(trade => trade.NetProfit));
var largetWinningLongTrade = LargesWiningTrade(Bot.History.Where(x => x.TradeType == TradeType.Buy).Select(trade => trade.NetProfit));
var largestWinningShortTrade = LargesWiningTrade(Bot.History.Where(x => x.TradeType == TradeType.Sell).Select(trade => trade.NetProfit));
backtestinresult += string.Format("Largest Winning Trade,{0},{1},{2}\n", largestWinningTrade, largetWinningLongTrade, largestWinningShortTrade);
var LosingTrades = GetLosingTrades(Bot.History.Select(trade => trade.NetProfit));
var LonglosingTrades = GetLosingTrades(Bot.History.Where(x => x.TradeType == TradeType.Buy).Select(trade => trade.NetProfit));
var ShortlosingTades = GetLosingTrades(Bot.History.Where(x => x.TradeType == TradeType.Sell).Select(trade => trade.NetProfit));
backtestinresult += string.Format("LosingTrades,{0},{1},{2}\n", LosingTrades, LonglosingTrades, ShortlosingTades);
var MaxConsLossTrades = MaxConsecutiveLoss("Trades");
var MaxConsLongLossTrades = MaxConsecutiveLoss("Long");
var MaxConsShortLossTrades = MaxConsecutiveLoss("Short");
backtestinresult += string.Format("Max Consecutive Losing Trades,{0},{1},{2}\n", MaxConsLossTrades, MaxConsLongLossTrades, MaxConsShortLossTrades);
var largestLosingTrade = LargestLosingTrade(Bot.History.Select(trade => trade.NetProfit));
var largestLosingLongTrade = LargestLosingTrade(Bot.History.Where(x => x.TradeType == TradeType.Buy).Select(trade => trade.NetProfit));
var largestLosingShortTrade = LargestLosingTrade(Bot.History.Where(x => x.TradeType == TradeType.Sell).Select(trade => trade.NetProfit));
backtestinresult += string.Format("Largest Losing Trade,{0},{1},{2}\n", largestLosingTrade, largestLosingLongTrade, largestLosingShortTrade);
var averageTrade = AverageTrade(Bot.History.Select(trade => trade.NetProfit));
var averageLongTrade = AverageTrade(Bot.History.Where(x => x.TradeType == TradeType.Buy).Select(trade => trade.NetProfit));
var averageShortTrade = AverageTrade(Bot.History.Where(x => x.TradeType == TradeType.Sell).Select(trade => trade.NetProfit));
backtestinresult += string.Format("Average Trade,{0},{1},{2}\n", averageTrade, averageLongTrade, averageShortTrade);
var sharpeRatio = SharpeSortino(false, Bot.History.Select(trade => trade.NetProfit));
var sharpeRatioLong = SharpeSortino(false, Bot.History.Where(x => x.TradeType == TradeType.Buy).Select(trade => trade.NetProfit));
var sharpeRatioShort = SharpeSortino(false, Bot.History.Where(x => x.TradeType == TradeType.Sell).Select(trade => trade.NetProfit));
backtestinresult += string.Format("Sharpe Ratio,{0},{1},{2}\n", sharpeRatio, sharpeRatioLong, sharpeRatioShort);
var sortinoRatio = SharpeSortino(true, Bot.History.Select(trade => trade.NetProfit));
var sortinoRatioLong = SharpeSortino(true, Bot.History.Where(x => x.TradeType == TradeType.Buy).Select(trade => trade.NetProfit));
var sortinoRatioShort = SharpeSortino(true, Bot.History.Where(x => x.TradeType == TradeType.Sell).Select(trade => trade.NetProfit));
backtestinresult += string.Format("Sortino Ratio,{0},{1},{2}\n", sortinoRatio, sortinoRatioLong, sortinoRatioShort);
File.AppendAllText(FullPath, backtestinresult + Environment.NewLine, Encoding.UTF8);
}
public void WriteOptimizationResult()
{
EquityResult = Bot.Account.Equity;
BalanceResult = Bot.Account.Balance;
NetProfitResult = GetNetProfit(Bot.History.Select(trade => trade.NetProfit));
TradesResult = GetTrades(Bot.History.Select(trade => trade.NetProfit));
WinningTradesResult = GetWiningTrades(Bot.History.Select(trade => trade.NetProfit));
LosingTradesResult = GetLosingTrades(Bot.History.Select(trade => trade.NetProfit));
ProfitFactorResult = GetProfitFactor(Bot.History.Select(trade => trade.NetProfit));
//var MaxBalanceDrawDownPct = MaxBalanceDrawDown;
//var MaxEquityDrawDownPct = MaxEquityDrawDown;
SharpeRatioResult = SharpeSortino(false, Bot.History.Select(trade => trade.NetProfit));
SortinoRatioResult = SharpeSortino(true, Bot.History.Select(trade => trade.NetProfit));
AverageTradeResult = AverageTrade(Bot.History.Select(trade => trade.NetProfit));
string data = string.Format("Pass {0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, {9}, {10}, {11}, {12}, {13}, {14}, {15}",
OptimizationPassId,SymbolTimeFrame,EquityResult, BalanceResult, NetProfitResult, TradesResult, WinningTradesResult, LosingTradesResult,
ProfitFactorResult, MaxEquityDrawDownPct, MaxBalanceDrawDownPct, MaxEquityDrawDown, MaxBalanceDrawDown, SharpeRatioResult, SortinoRatioResult, AverageTradeResult);
bool isEmpty = !parametersValue.Any();
if (!isEmpty)
{
var result = "," + string.Join(",", parametersValue.Select(s => $"{s}"));
data += result;
}
EditLine(data, FullPath, OptimizationPassId +1);
}
public void GetTradeDrawDownData()
{
GetMaxBalanceDrawDown(true);
GetMaxBalanceDrawDown(false);
GetMaxEquityDrawDown(true);
GetMaxEquityDrawDown(false);
}
public double GetNetProfit(IEnumerable<double> vals)
{
var netprofit = vals.Where(x => x >= 0).Sum();
var netloss = vals.Where(x => x < 0).Sum();
var profit = (netprofit - (netloss * -1));
return (Math.Round(profit, 2));
}
public int GetTrades(IEnumerable<double> vals)
{
var totaltrades = vals.Count();
return totaltrades;
}
public int GetWiningTrades(IEnumerable<double> vals)
{
var positiveTrades = vals.Where(x => x >= 0).Count();
return positiveTrades;
}
public int GetLosingTrades(IEnumerable<double> vals)
{
var negativeTrades = vals.Where(x => x < 0).Count();
return negativeTrades;
}
public double GetProfitFactor(IEnumerable<double> vals)
{
var netprofit = vals.Where(trade => trade >= 0).Sum();
var netloss = vals.Where(x => x < 0).Sum();
var profitFactor = (netprofit / netloss);
return (Math.Round(profitFactor, 2));
}
public void GetMaxBalanceDrawDown(bool isPct)
{
var Balance = Bot.Account.Balance;
if (Balance >= MaxBalance)
MaxBalance = Balance;
if (Balance < MaxBalance)
{
var NewLowBalance = Balance;
if (isPct)
{
var CurrentDrawDown = MaxEquityBalanceDrawDownToPct(MaxBalance, NewLowBalance);
if (MaxBalanceDrawDownPct < CurrentDrawDown)
{
MaxBalanceDrawDownPct = Math.Round(CurrentDrawDown, 2);
}
}
else
{
var CurrentDrawDown = MaxEquityBalanceDrawDown(MaxBalance, NewLowBalance);
if (MaxBalanceDrawDown < CurrentDrawDown)
{
MaxBalanceDrawDown = Math.Round(CurrentDrawDown, 2);
}
}
}
}
public void GetMaxEquityDrawDown(bool isPct)
{
var Equity = Bot.Account.Equity;
if (Equity > MaxEquity)
MaxEquity = Equity;
if (Equity < MaxEquity)
{
var NewLowEquity = Equity;
if (isPct)
{
var CurrentDrawDown = MaxEquityBalanceDrawDownToPct(MaxEquity, NewLowEquity);
if (MaxEquityDrawDownPct < CurrentDrawDown)
{
MaxEquityDrawDownPct = Math.Round(CurrentDrawDown, 2);
}
}
else
{
var CurrentDrawDown = MaxEquityBalanceDrawDown(MaxEquity, NewLowEquity);
if (MaxEquityDrawDown < CurrentDrawDown)
{
MaxEquityDrawDown = Math.Round(CurrentDrawDown, 2);
}
}
}
}
private static double MaxEquityBalanceDrawDownToPct(double Max, double Min)
{
var difference = Max - Min;
var pct = difference / Max * 100;
return pct;
}
private static double MaxEquityBalanceDrawDown(double Max, double Min)
{
var difference = Max - Min;
return difference;
}
public double AverageTrade(IEnumerable<double> vals)
{
var totaltrades = vals.Count();
var netprofit = vals.Sum();
return Math.Round((netprofit / totaltrades), 2);
}
public static double SharpeSortino(bool isSortino, IEnumerable<double> vals)
{
if (vals.Count() < 2) return double.NaN;
double average = vals.Average();
double sd = Math.Sqrt(vals.Where(val => (!isSortino || val < average)).Select(val => (val - average) * (val - average)).Sum() / (vals.Count() - 1));
return Math.Round((average / sd), 2);
}
public double GetCommissions(IEnumerable<double> vals)
{
var commissions = vals.Sum();
return Math.Round((commissions), 2);
}
public int MaxConsecutiveWin(string type)
{
var maxwinning = 0;
var wincounter = 0;
var lossescounter = 0;
var maxlosses = 0;
if (type == "Long")
{
foreach (HistoricalTrade trade in Bot.History)
{
if (trade.NetProfit >= 0 && trade.TradeType == TradeType.Buy)
{
if (lossescounter > 0)
lossescounter = 0;
wincounter += 1;
if (wincounter > maxwinning)
maxwinning = wincounter;
}
else if (trade.NetProfit < 0 && trade.TradeType == TradeType.Buy)
wincounter = 0;
}
}
else if (type == "Short")
{
foreach (HistoricalTrade trade in Bot.History)
{
if (trade.NetProfit >= 0 && trade.TradeType == TradeType.Sell)
{
if (lossescounter > 0)
lossescounter = 0;
wincounter += 1;
if (wincounter > maxwinning)
maxwinning = wincounter;
}
else if (trade.NetProfit < 0 && trade.TradeType == TradeType.Sell)
wincounter = 0;
}
}
else
{
foreach (HistoricalTrade trade in Bot.History)
{
if (trade.NetProfit >= 0)
{
if (lossescounter > 0)
lossescounter = 0;
wincounter += 1;
if (wincounter > maxwinning)
maxwinning = wincounter;
}
else if (trade.NetProfit < 0)
{
if (wincounter > 0)
wincounter = 0;
lossescounter += 1;
if (lossescounter > maxlosses)
maxlosses = lossescounter;
}
}
}
return maxwinning;
}
public double LargesWiningTrade(IEnumerable<double> vals)
{
var max = vals.Where(x => x >= 0).Max();
return max;
}
public double LargestLosingTrade(IEnumerable<double> vals)
{
var min = vals.Where(x => x < 0).Min();
return min;
}
private int MaxConsecutiveLoss(string type)
{
var maxwinning = 0;
var maxlosses = 0;
var wincounter = 0;
var lossescounter = 0;
if (type == "Long")
{
foreach (HistoricalTrade trade in Bot.History)
{
if (trade.NetProfit >= 0 && trade.TradeType == TradeType.Buy)
lossescounter = 0;
else if (trade.NetProfit < 0 && trade.TradeType == TradeType.Buy)
{
if (wincounter > 0)
wincounter = 0;
lossescounter += 1;
if (lossescounter > maxlosses)
maxlosses = lossescounter;
}
}
}
else if (type == "Short")
{
foreach (HistoricalTrade trade in Bot.History)
{
if (trade.NetProfit >= 0 && trade.TradeType == TradeType.Sell)
lossescounter = 0;
else if (trade.NetProfit < 0 && trade.TradeType == TradeType.Sell)
{
wincounter = 0;
lossescounter += 1;
if (lossescounter > maxlosses)
maxlosses = lossescounter;
}
}
}
else
{
foreach (HistoricalTrade trade in Bot.History)
{
if (trade.NetProfit >= 0)
{
if (lossescounter > 0)
lossescounter = 0;
wincounter += 1;
if (wincounter > maxwinning)
maxwinning = wincounter;
}
else if (trade.NetProfit < 0)
{
if (wincounter > 0)
wincounter = 0;
lossescounter += 1;
if (lossescounter > maxlosses)
maxlosses = lossescounter;
}
}
}
return maxlosses;
}
public void SetSymbolTimeFrame()
{
var mystring = Bot.TimeFrame.ToString();
bool isDigitString = mystring.Any(c => char.IsDigit(c));
var timeframeString = "";
if(!isDigitString)
{
if(mystring == "Daily")
timeframeString = "1 Day";
else
timeframeString = "1 " + Bot.TimeFrame.ToString();
}
else
{
Regex re = new Regex(@"([a-zA-Z]+)(\d+)");
Match result = re.Match(mystring);
string alphaPart = result.Groups[1].Value;
string numberPart = result.Groups[2].Value;
timeframeString = numberPart + " " + alphaPart + "s";
}
SymbolTimeFrame = Bot.Symbol.Name + "-" + timeframeString;
}
public void CreateOptimizationDataFile()
{
if (TotalLines() == 0)
{
OptimizationPassId = 1;
File.AppendAllText(FullPath, header + Environment.NewLine, Encoding.UTF8);
string data = string.Format("Pass {0}", OptimizationPassId);
File.AppendAllText(FullPath, data + Environment.NewLine, Encoding.UTF8);
}
else if (TotalLines() == 1)
{
var Line1 = File.ReadLines(FullPath).First();
OptimizationPassId = 1;
if (Line1 != header)
{
string data = string.Format("Pass {0}", OptimizationPassId);
File.AppendAllText(FullPath, data + Environment.NewLine, Encoding.UTF8);
}
else
{
string data = string.Format("Pass {0}", OptimizationPassId);
File.AppendAllText(FullPath, data + Environment.NewLine, Encoding.UTF8);
}
}
else
{
var lines = TotalLines();
OptimizationPassId = lines;
string data = string.Format("Pass {0}", OptimizationPassId);
File.AppendAllText(FullPath, data + Environment.NewLine, Encoding.UTF8);
}
}
public void EditLine(string newText, string fileName, int line)
{
string[] arrayLines = File.ReadAllLines(fileName);
arrayLines[line - 1] = newText;
File.WriteAllLines(fileName, arrayLines, Encoding.UTF8);
}
public int TotalLines()
{
if (!File.Exists(FullPath))
return 0;
using (StreamReader r = new StreamReader(FullPath))
{
int i = 0;
while (r.ReadLine() != null)
{
i++;
}
return i;
}
}
}
}
TraderExperto
Joined on 07.06.2019
- Distribution: Free
- Language: C#
- Trading platform: cTrader Automate
- File name: MACD Example Data Extraction.algo
- Rating: 5
- Installs: 681
- Modified: 02/05/2023 21:51
Comments
Hi. I lke the work you've done here
This line of code will fail "if (Currencies.ContainsKey(Bot.Account.Asset.Name))" because Bot.Account.Asset.Name will give a 6 character string i.e. “EURUSD” and tis will not match “CHF”, "EUR" etc
Hi, I think your site might be having browser compatibility issues. When I look at your blog site in Chrome, it looks fine but when opening in Internet Explorer, it has some overlapping. I just wanted to give you a quick heads up! Other then that, superb blog!Slot Gacor
You could definitely see your skills in the work you write. The world hopes for even more passionate writers like you who aren’t afraid to say how they believe. Always follow your heart.Packers and Movers Mumbai to Ahmedabad
Woah I’m just truly digging the design and style/strategy of this web page. It is easy, nevertheless excellent. Much more frequently than not it is tough to acquire the excellent involving excellent usability along with visual appearance. I have to say you have carried out a amazing task. In addition, your web site starts super fast personally with World wide web explorer. Exceptional Web sitePackers and Movers Faridabad
Are you sure your calculation of the Sharpe ratio is correct? I ask because i want to do something similar and have the bot populate an excel spreadsheet after each optimization pass has ended