Description
Hey Guys i'm happy to share with you some of my personal tools that i developed to help me extract data from Backtesting and Optimization on my Cbots.
This is a Class and Template for your Cbot, that can extract Backtesting Data and Optimization Data and write it to a CSV file for further Analysis on Excel or any other spreadsheet software.
In this link you will find a MACD Cbot Example for testing it,Link to MACD Cbot
Here i will be sharing some screenshots for the pieaces of the code so that you can easily implement to your Cbot.
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
In the screenshot above you have all the libriaries needed to make the class work properly
In this second screenshot you the parameters need, for this class, and it is highlighted the parameters for the files where the data will be written and also the CBotPerformanceDaataExtractor Instance declaration.
In this screenshot you have multiple parameters that are not mandatory and they serves just as a example on how you can add paramaters to be written by the class on the file.
Here in this screenshot i highlighted the parts that you must take attention the List ParametersName and ParametersValue they serve for saving your cBots Parameters name and values to the file. If you don't want them you can make the list empty as it is shown and the commented code above them. Still in the OnStart Method you can copy and paste the rest of the code to your OnStart Method as it is shown in the screenshot and in the code.
This is a importantant part. If you don't use OnTick method you need to call it so that the calculation for drawdown balance and equity are done correctly. Just copy and paste this code to your cbot as it is shown in the screenshot.
On your OnStop Method you need to put the code that will be writting all the results of the optimization, and backtesting results. Copy and Past this part as in the screenshot.
During Optimization you also can enable the Timeframe option for multiple Timeframe testing. Be aware to not check the last option (Enable Data Extraction). If you checkbox it it will not write all the results. The picture above is just serves as an example.
This is the result of the Optimization Data Written to a CSV File. For the Optimization Pass Field the cbot class writes to the file in the order that it is finishing, so that for some reason it some times doesn't match the same Pass number as it is shown in the Ctrader Platform. The most important part is that all the data is correctly saved for every optimization test.
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(AccessRights = AccessRights.FullAccess)]
public class CbotDataExtractionClassv10 : 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 = 0.01)]
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;
protected override void OnStart()
{
//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();
}
}
} // End of your Main Class
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: Cbot Data Extraction Class v1.0.algo
- Rating: 0
- Installs: 632
- Modified: 02/05/2023 21:45
Comments
I was rattling pleased to find this site on bing, just what I was looking for : D also bookmarked .how to be a credit card processor
Thank you, I have recently been looking for info approximately this topic for a while and yours is the greatest I’ve found out so far. However, what about the conclusion? Are you certain concerning the source?Packers and Movers Noida
I discovered your blog post web site online and appearance several of your early posts. Maintain on the really good operate. I additional encourage Rss to my MSN News Reader. Looking for forward to reading far more of your stuff at a later time!…Slot