public void BacktestMACD(decimal entryPrice, decimal exitPrice) { // 12/26 "slow" moving average for BNBUSD...buy when slow ma hits -0.2 and scale in more at -0.4 var candles = ReadCandles("BINANCE", "BNBUSDT", 60); //var ema = GMath.GetCandlesEMA(candles, 26); var macd = GMath.GetCandlesMACD(candles, 12, 26, 9); var backtest = new Backtest(string.Format("Entry:{0} Exit:{1}", entryPrice, exitPrice)); BacktestRoundTrip inTrade = null; foreach (var kv in macd) { if (inTrade != null) { if (kv.Value.Signal >= exitPrice) { inTrade.Exit = new BacktestTrade(OrderSide.Sell, exitPrice, kv.Key); //Console.WriteLine("EXIT : {0} {1:0.0000}", kv.Key, kv.Value.Signal); backtest.Add(inTrade); inTrade = null; } } else { if (kv.Value.Signal <= entryPrice) { inTrade = new BacktestRoundTrip(); inTrade.Entry = new BacktestTrade(OrderSide.Buy, entryPrice, kv.Key); //Console.WriteLine("ENTRY: {0} {1:0.0000}", kv.Key, kv.Value.Signal); } } } backtest.PrintTrades(); }
public override DatedDataCollectionGen<double> GenerateWeightSeries(Backtest.ProductBase product_, DateTime? minDate_) { var pxs = product_.Prices; var mas = new DatedDataCollectionGen<double>[m_windows.Length]; for (int i = 0; i < mas.Length; ++i) mas[i] = HelperMethods.GetMA(pxs, m_windows[i]); double[] scores = new double[mas[0].Length]; var dates = mas[0].Dates; for (int i = 0; i < dates.Length; ++i) { var date = dates[i]; var px = pxs.ValueOnDate(date); for (int m = 0; m < mas.Length; ++m) { var maValue = mas[m].ValueOnDate(date); if (px > maValue) scores[i] += m_weightings[m_windows[m]]; else scores[i] -= m_weightings[m_windows[m]]; } } return new DatedDataCollectionGen<double>(dates, scores); }
private static void TestShingle(int s) { using (var db = new Db()) { var sh = db.Shingles.Find(s); Console.Write($"{sh.text}"); var b = new Backtest { StrategyNr = strategyNr, TakeProfitPercent = 3, StopLossPercent = 1.5m, DaysToTimeout = 5, SignalName = s + " " + sh.text, }; var sus = db.ShingleUses.Where(x => x.ShingleID == s && x.Article.Ticker != null).OrderBy(x => x.Article.ReceivedUTC).ToArray(); decimal totalProfit = 0; var PredictionList = new List <Prediction>(); var LastTrade = DateTime.MinValue; foreach (var su in sus) { if (su.Article.ReceivedUTC < LastTrade) { continue; } Prediction t = Trade(DirectionType.Sell, su.Article.Ticker, su.Article.ReceivedUTC, b.TakeProfitPercent, b.StopLossPercent, b.Comment, b.DaysToTimeout, b.StrategyNr); if (t != null) { PredictionList.Add(t); totalProfit += t.Profit; LastTrade = t.TimeClose; } } if (PredictionList.Count > 0) { b.StrategyNr = strategyNr++; b.Wins = PredictionList.Count(x => x.Profit > 0); b.Loses = PredictionList.Count(x => x.Profit <= 0); b.Takeprofits = PredictionList.Count(x => x.Exit == ExitReason.TakeProfit); b.Stoploses = PredictionList.Count(x => x.Exit == ExitReason.StopLoss); b.Timeouts = PredictionList.Count(x => x.Exit == ExitReason.Timeout); b.Buys = PredictionList.Count(x => x.BuySignal); b.Sells = PredictionList.Count(x => !x.BuySignal); b.BuyProfit = PredictionList.Where(x => x.BuySignal).Select(x => x.Profit).Sum(); b.SellProfit = PredictionList.Where(x => !x.BuySignal).Select(x => x.Profit).Sum(); b.WinProfit = PredictionList.Where(x => x.Profit > 0).Select(x => x.Profit).Sum(); b.LossProfit = PredictionList.Where(x => x.Profit < 0).Select(x => x.Profit).Sum(); b.TimeoutProfit = PredictionList.Where(x => x.Exit == ExitReason.Timeout).Select(x => x.Profit).Sum(); b.AverageTradeLength = PredictionList.Select(x => (decimal)((x.TimeClose - x.TimeOpen).Days)).Average(); b.TimeCalculated = DateTime.Now; b.TillDate = new DateTime(1900, 1, 1); b.FromDate = new DateTime(1900, 1, 1); db.Backtests.Add(b); db.SaveChanges(); } Console.WriteLine($" {totalProfit}"); } }
public static string Backtest(string buyScript, string sellScript, List <Bar> bars) { Backtest backtest = new Backtest(); backtest.License = TradeScriptKey; backtest.OnScriptError += backtest_OnError; AppendData(backtest, bars); return(backtest.RunBacktest(buyScript, sellScript, string.Empty, string.Empty, 0.00001f)); }
static void Main(string[] args) { //Framework.Current.StrategyManager.Mode = StrategyMode.Live; //SmartQuant.Scenario scenario = new IndicatorTest(Framework.Current); //SmartQuant.Scenario scenario = new Backtest86400(Framework.Current); //SmartQuant.Scenario scenario = new Realtime86400(Framework.Current); // 在使用Backtest之前,需要先使用 PbTickDataExport._Main 生成 数据文件 D:\1.data 才能测试 SmartQuant.Scenario scenario = new Backtest(Framework.Current); //SmartQuant.Scenario scenario = new RealtimeLoadOnStart(Framework.Current); //SmartQuant.Scenario scenario = new BacktestLoadOnStart(Framework.Current); scenario.Run(); }
protected override void chartSignal(Backtest.ProductBase product_, Controls.LineChartDataDisplay chart_) { chart_.ClearSeries(); chart_.AddSeries(product_.Prices, "Prices", 40, "##0.0##"); chart_.AddSeries(HelperMethods.GetRollingStat(product_.Prices, MA, Statistics.Average), "MA", 40, "##0.0##"); var series = product_.Prices; var rollingStdev = HelperMethods.GetRollingStat(product_.Prices.ToReturns(), 252, x => Statistics.Stdev(x)*Math.Sqrt(252d)); chart_.AddSeries(rollingStdev, "Stdev", 80, "##0.0#%"); chart_.AddSeries( HelperMethods.GetRollingStat(rollingStdev, 252, x => HelperMethods.GetPercentRank(x, x.Length - 1)), "Stdev_Pctile", 120, "0.00"); }
public override void Chart(Controls.LineChartDataDisplay lcdd_, Backtest.ProductBase product_) { var pxs = product_.Prices; lcdd_.ClearSeries(); lcdd_.AddSeries(pxs, string.Format("{0} price", product_.Name), 40, "##0.0##"); if (MA1.HasValue) lcdd_.AddSeries(HelperMethods.GetRollingStat(pxs, MA1.Value, Statistics.Average), string.Format("MA({0})", MA1), 40, "##0.0##"); if(MA2.HasValue) lcdd_.AddSeries(HelperMethods.GetRollingStat(pxs, MA2.Value, Statistics.Average), string.Format("MA({0})", MA2), 40, "##0.0##"); if (MA3.HasValue) lcdd_.AddSeries(HelperMethods.GetRollingStat(pxs, MA3.Value, Statistics.Average), string.Format("MA({0})", MA3), 40, "##0.0##"); }
public override DatedDataCollectionGen<double> GenerateWeightSeries(Backtest.ProductBase product_, DateTime? minDate_) { var pxs = product_.Prices; var mas = HelperMethods.GetRollingStat(pxs, MA, Statistics.Average); var scores = new double[mas.Length]; for (int i = 0; i < scores.Length; ++i) { var px = pxs.ValueOnDate(mas.Dates[i]); var ma = mas.Data[i]; if (px > ma) scores[i] = 1d; else scores[i] = -1d; } return new DatedDataCollectionGen<double>(mas.Dates, scores); }
public ctlBackTest(frmMain2 oMain, ctlData oData) { InitializeComponent(); m_frmMain = oMain; m_ctlData = oData; oBacktest = new BacktestClass { License = "XRT93NQR79ABTW788XR48" }; oScript = new ScriptOutputClass { License = "XRT93NQR79ABTW788XR48" }; GetScriptNames(); txtBars.GotFocus += (sender, e) => Text_Focus((TextBoxBase)sender); txtInterval.GotFocus += (sender, e) => Text_Focus((TextBoxBase)sender); txtSymbol.GotFocus += (sender, e) => Text_Focus((TextBoxBase)sender); oScript.ScriptError += oScript_ScriptError; oBacktest.ScriptError += oBacktest_ScriptError; }
/// <summary> /// Wait for the backtest to complete /// </summary> /// <param name="projectId">Project id to scan</param> /// <param name="backtestId">Backtest id previously started</param> /// <returns>Completed backtest object</returns> private Backtest WaitForBacktestCompletion(int projectId, string backtestId) { var result = new Backtest(); var finish = DateTime.Now.AddSeconds(60); while (DateTime.Now < finish) { result = _api.ReadBacktest(projectId, backtestId); if (result.Progress == 1) { break; } if (!result.Success) { break; } Thread.Sleep(1000); } return(result); }
public ctlBacktest(frmMain oMain, ctlData oData) { InitializeComponent(); _mFrmMain = oMain; _mCtlData = oData; _oBacktest = new BacktestClass { License = "XRT93NQR79ABTW788XR48" }; _oScript = new ScriptOutputClass { License = "XRT93NQR79ABTW788XR48" }; txtBars.GotFocus += (sender, e) => TextFocus((TextBoxBase)sender); txtInterval.GotFocus += (sender, e) => TextFocus((TextBoxBase)sender); txtSymbol.GotFocus += (sender, e) => TextFocus((TextBoxBase)sender); _oScript.ScriptError += OScriptScriptError; _oBacktest.ScriptError += OBacktestScriptError; }
public override DatedDataCollectionGen<double> GenerateWeightSeries(Backtest.ProductBase product_, DateTime? wtsMinDate_) { return GenerateWeightSeries(product_.Prices, wtsMinDate_); }
public static void BackTest(string Date, string Weeks) { /////////////////////////// /// /// Setting backtest object /// ////////////////////////// Backtest Mybacktest = new Backtest(); Backtest Mybacktest_adj = new Backtest(); // Initial the two backtest Mybacktest.Init(); Mybacktest_adj.Init(); /////////////////////////// /// /// Setting data container to store the information /// outside the for loop /// /////////////////////////// // setting netvalue lists for both standard strategy and dynamic strategy List <double> Hisc_netValue = new List <double>(); List <double> Adj_netValue = new List <double>(); // setting lists to store Fixed Income ETFs and Equity ETFs // we are holding during this trading week for the caculation of // Turnover Utility function List <string> ETFs_holding_FI = new List <string>(); List <string> ETFs_holding_Equ = new List <string>(); // setting matrix to store the trading history during this backtest string[][] trading_history_ETF = new string[Convert.ToInt64(Weeks)][]; double[][] trading_history_allocation = new double[Convert.ToInt64(Weeks)][]; double[][] ADJtrading_history_allocation = new double[Convert.ToInt64(Weeks)][]; // setting two variable drawdown and position ratio for the caculation // in Dynamic strategy, position ratio means the percentage of Fixed Income // ETFs we are currently holding double DrawDown = 0; double Position_ratio = 0.2; int FI_holding_weeks = 0; int Equ_holding_weeks = 0; double[] FI_holding_allocation = new double[5]; double[] Equ_holding_allocation = new double[5]; ////////////////////////////////// /// /// For loop backtest /// ///////////////////////////////// for (int i = 0; i < Convert.ToInt64(Weeks); i++) { // seting Datapreprocessing class for both Fixed Income ETFs and Equity ETFs DataPreProcessing pro_FI = new DataPreProcessing(); DataPreProcessing pro_Equ = new DataPreProcessing(); // caculate the date of today start from the 'Date' // which is given by backtest function var Today = DateTime.Parse(Date).AddDays(i * 7); // print the date we trained the model and trade Console.WriteLine("Date: {0}", Today.ToString()); // cleaning data use data preprocessing class pro_FI.Run(Today.ToString(), 112, "Fixed Income"); pro_Equ.Run(Today.ToString(), 112, "Equity"); // Set prediction vector double[] predictions_FI = new double[pro_FI.Trade_ETF.Count]; double[] predictions_Equ = new double[pro_Equ.Trade_ETF.Count]; // Set blend ETFs list to store the Top 10 etfs which is going to be // longed by the algorithm List <string> Blend_ETFs = new List <string>(); ///////////////////////////// /// /////// /// FI ETF prediction /////// /// /////// ///////////////////////////// for (int j = 0; j < pro_FI.Trade_ETF.Count; j++) { // Grab the data from the datapreprocessing object class var y = pro_FI.Target_List[j]; var fy = new FrameBuilder.Columns <DateTime, string> { { "Y", y } }.Frame; var data = pro_FI.Feature_List[j].Join(fy); var pred_Features = pro_FI.pred_Feature_List[j]; data.SaveCsv("dataset.csv"); // Training machine learning and predict var prediction = Learning.FitGBT(pred_Features); predictions_FI[j] = prediction; } // Get the minimum scores of top 5 ETF var hold_FI = PredRanking(predictions_FI, 5); // Get the namelist of top 5 ETF List <string> ETFs_FI = new List <string>(); for (int m = 0; m < pro_FI.Trade_ETF.Count; m++) { if (predictions_FI[m] >= hold_FI) { ETFs_FI.Add(pro_FI.Trade_ETF[m]); } } // Caculate the bid-ask spread cost if trade all 5 ETFs given by algorithm double[] FixedIncomeSpread = new double[5]; FixedIncomeSpread = GetBidAskSpread(ETFs_FI.ToArray()); // Cacualte the Unitility and decide if we should trade this week if (i == 0) { ETFs_holding_FI = ETFs_FI; } else { // get all prediction results of both holding etf and etfs which we may be going to trade double[] holding_pred = ETFname2Prediction(ETFs_holding_FI, predictions_FI, pro_FI); double[] long_pred = ETFname2Prediction(ETFs_FI, predictions_FI, pro_FI); // caculate the trade diff which is the utility of trading this week double trade_diff = long_pred.Sum() - holding_pred.Sum() - CaculateRebalanceCost(ETFs_FI, ETFs_holding_FI, FI_holding_allocation, pro_FI); // check if it is worth of trading if (trade_diff < 0) { // It is not worth of trading and ETFs portfolio will be same FI_holding_weeks += 1; ETFs_FI = ETFs_holding_FI; // setting spread equals to 0 because we are not going to trade this week FixedIncomeSpread = new double[] { 0, 0, 0, 0, 0 }; } else { FI_holding_weeks = 0; // It is worth of changing positions and trading this week ! // recaculate the spread costs because we may not going to trade all // ETFs which we are holding right now. for (int m = 0; m < 5; m++) { for (int n = 0; n < 5; n++) { if (ETFs_FI[m] == ETFs_holding_FI[n]) { FixedIncomeSpread[m] = 0; } else { continue; } } } // resetting the fixed income ETFs we are holding ETFs_holding_FI = ETFs_FI; } } Console.WriteLine("Long the following ETFs: "); // Store the Fixed Income ETFs namelist to blend ETFs list for (int n = 0; n < ETFs_FI.Count; n++) { Console.WriteLine(ETFs_FI[n]); Blend_ETFs.Add(ETFs_FI[n]); } /////////////////////////////////// /// /////// /// Equity ETF prediction /////// /// /////// /////////////////////////////////// for (int j = 0; j < pro_Equ.Trade_ETF.Count; j++) { // Run machine learning and predict next week for all ETFss var y = pro_Equ.Target_List[j]; var fy = new FrameBuilder.Columns <DateTime, string> { { "Y", y } }.Frame; var data = pro_Equ.Feature_List[j].Join(fy); var pred_Features = pro_Equ.pred_Feature_List[j]; data.SaveCsv("dataset.csv"); var prediction = Learning.FitGBT(pred_Features); predictions_Equ[j] = prediction; } List <string> ETFs_Equ = new List <string>(); // Find the min score of top 5 best ETFs var hold_Equ = PredRanking(predictions_Equ, 5); for (int m = 0; m < pro_Equ.Trade_ETF.Count; m++) { if (predictions_Equ[m] >= hold_Equ) { ETFs_Equ.Add(pro_Equ.Trade_ETF[m]); } } // caculate the bidAsk Spread double[] EquityBASpread = new double[5]; EquityBASpread = GetBidAskSpread(ETFs_Equ.ToArray()); if (i == 0) { ETFs_holding_Equ = ETFs_Equ; } else { double[] holding_pred = ETFname2Prediction(ETFs_holding_Equ, predictions_Equ, pro_Equ); double[] long_pred = ETFname2Prediction(ETFs_Equ, predictions_Equ, pro_Equ); // Caculate the Utility double trade_diff = long_pred.Sum() - holding_pred.Sum() - CaculateRebalanceCost(ETFs_Equ, ETFs_holding_Equ, Equ_holding_allocation, pro_Equ); // check if it is worth of trading this week if (trade_diff < 0) { Equ_holding_weeks += 1; ETFs_Equ = ETFs_holding_Equ; EquityBASpread = new double[] { 0, 0, 0, 0, 0 }; } else { // Recacluate the spread costs Equ_holding_weeks = 0; for (int m = 0; m < 5; m++) { for (int n = 0; n < 5; n++) { if (ETFs_Equ[m] == ETFs_holding_Equ[n]) { EquityBASpread[m] = 0; } else { continue; } } } ETFs_holding_Equ = ETFs_Equ; } } // Store the Equity ETFs we are going to long in Blend ETFs list for (int n = 0; n < ETFs_Equ.Count; n++) { Console.WriteLine(ETFs_Equ[n]); Blend_ETFs.Add(ETFs_Equ[n]); } // Caculate optimized allocations for both Fixed income and Equity ETFs ////////////////////////////// Console.WriteLine("Holding weeks for current Fixed Income ETFs is {0}", FI_holding_weeks); Console.WriteLine("Holding weeks for current Equity ETFs is {0}", Equ_holding_weeks); double[] AllocationFI = new double[5]; if (FI_holding_weeks == 0) { AllocationFI = PO.ETF2AllocationOwnOptim(ETFs_FI, pro_FI); FI_holding_allocation = AllocationFI; } else if (FI_holding_weeks < 15) { AllocationFI = FI_holding_allocation; } else { FI_holding_weeks = 0; AllocationFI = PO.ETF2AllocationOwnOptim(ETFs_FI, pro_FI); FI_holding_allocation = AllocationFI; } ////////////////////////////// double[] AllocationEqu = new double[5]; if (Equ_holding_weeks == 0) { AllocationEqu = PO.ETF2AllocationOwnOptim(ETFs_Equ, pro_Equ); Equ_holding_allocation = AllocationEqu; } else if (Equ_holding_weeks < 15) { AllocationEqu = Equ_holding_allocation; } else { Equ_holding_weeks = 0; AllocationEqu = PO.ETF2AllocationOwnOptim(ETFs_Equ, pro_Equ); Equ_holding_allocation = AllocationEqu; } ////////////////////////////// // Setting allocations which is an array to store allocations for strandard strategy double[] allocations = new double[10]; for (int fi = 0; fi < 5; fi++) { allocations[fi] = AllocationFI[fi] * 0.2; } for (int equ = 0; equ < 5; equ++) { allocations[equ + 5] = AllocationEqu[equ] * 0.8; } // Setting ALLOCATION which is an array to store allocations for strandard strategy double[] ALLOCATION = new double[10]; for (int fi = 0; fi < 5; fi++) { ALLOCATION[fi] = AllocationFI[fi] * Position_ratio; } for (int equ = 0; equ < 5; equ++) { ALLOCATION[equ + 5] = AllocationEqu[equ] * (1 - Position_ratio); } // Transform ETFs list to an array string[] ETFs = new string[10]; for (int etf = 0; etf < 10; etf++) { ETFs[etf] = Blend_ETFs[etf]; } // Storing the ETFs trading history and allocations trading_history_ETF[i] = new string[10]; trading_history_ETF[i] = ETFs; trading_history_allocation[i] = new double[10]; trading_history_allocation[i] = allocations; ADJtrading_history_allocation[i] = new double[10]; ADJtrading_history_allocation[i] = ALLOCATION; // Get the spread array for all ETFs double[] spread = new double[10]; Array.Copy(FixedIncomeSpread, spread, FixedIncomeSpread.Length); Array.Copy(EquityBASpread, 0, spread, FixedIncomeSpread.Length, EquityBASpread.Length); // Caculate the weighted spread for the adjustment in netvalue double weighted_spread = 0; for (int spreadItem = 0; spreadItem < 10; spreadItem++) { weighted_spread += allocations[spreadItem] * spread[spreadItem]; } // clearing the NetValue Hisc_netValue.Add(Mybacktest.Rebalance(Today, ETFs, allocations) * (1 - weighted_spread)); Adj_netValue.Add(Mybacktest_adj.Rebalance(Today, ETFs, ALLOCATION) * (1 - weighted_spread)); // Caculate the current drawdown and adjust the position ratio which is // the percentage for the fixed income ETFs if (i == 0) { DrawDown = 0; } else { DrawDown = 1 - Hisc_netValue.Last() / Hisc_netValue.Max(); } // Adjust the position ratio if (DrawDown > 0.1) { Position_ratio = 0.8; } else if (DrawDown > 0.08) { Position_ratio = 0.6; } else if (DrawDown > 0.05) { Position_ratio = 0.4; } else { Position_ratio = 0.2; } // Print out the current drawdown and position ratio. Console.WriteLine("Current drawdown is: {0}", DrawDown); Console.WriteLine("Fixed Income has been adjusted to: {0} %", Position_ratio * 100); } // Result analysis for NetValue ///////////////////// /// /// Backtest Metrics of Strandard Strategy /// //////////////////// var StrategyNetValue = Hisc_netValue.ToArray(); double MaxDD = 0; for (int i = 1; i < StrategyNetValue.Length; i++) { var MaxNetValue = StrategyNetValue.Take(i).Max(); double drawdown = 1 - StrategyNetValue[i] / MaxNetValue; if (drawdown > MaxDD) { MaxDD = drawdown; } } Console.WriteLine("Maximum drawdown of This Strategy is: {0}", MaxDD); var AnnualReturn = Math.Log(StrategyNetValue.Last()) / (Convert.ToDouble(Weeks) / 50); Console.WriteLine("Annual Return of This Strategy is: {0}", AnnualReturn); var StrategyReturn = NetValue2Return(StrategyNetValue); Console.WriteLine("Standard Deviation of This Strategy is: {0}", Statistics.StandardDeviation(StrategyReturn)); double[] BTmetrics = new double[3]; BTmetrics[0] = AnnualReturn; BTmetrics[1] = MaxDD; BTmetrics[2] = Statistics.StandardDeviation(StrategyReturn) * Math.Sqrt(50); // Result analysis for AdjNetValue ///////////////////// /// /// Backtest Metrics of Dynamic Strategy /// ///////////////////// var ADJStrategyNetValue = Adj_netValue.ToArray(); double ADJMaxDD = 0; for (int i = 1; i < ADJStrategyNetValue.Length; i++) { var MaxNetValue = ADJStrategyNetValue.Take(i).Max(); double drawdown = 1 - ADJStrategyNetValue[i] / MaxNetValue; if (drawdown > ADJMaxDD) { ADJMaxDD = drawdown; } } Console.WriteLine("Maximum drawdown of ADJ Strategy is: {0}", ADJMaxDD); var ADJAnnualReturn = Math.Log(ADJStrategyNetValue.Last()) / (Convert.ToDouble(Weeks) / 50); Console.WriteLine("Annual Return of ADJ Strategy is: {0}", ADJAnnualReturn); var ADJStrategyReturn = NetValue2Return(ADJStrategyNetValue); Console.WriteLine("Standard Deviation of This Strategy is: {0}", Statistics.StandardDeviation(ADJStrategyReturn)); double[] ADJBTmetrics = new double[3]; ADJBTmetrics[0] = ADJAnnualReturn; ADJBTmetrics[1] = ADJMaxDD; ADJBTmetrics[2] = Statistics.StandardDeviation(ADJStrategyReturn) * Math.Sqrt(50); // Output all results to CSV // Without position adjustment SaveArrayAsCSV_(trading_history_allocation, "StrandardTradingHistoryAllocation.csv"); SaveArrayAsCSV(BTmetrics, "StandardBacktestMetrics.csv"); SaveArrayAsCSV(StrategyNetValue, "StandardNet_value.csv"); // With position adjustmnet SaveArrayAsCSV_(ADJtrading_history_allocation, "DynamicTradingHistoryAllocation.csv"); SaveArrayAsCSV(ADJBTmetrics, "DynamicBacktestMetrics.csv"); SaveArrayAsCSV(ADJStrategyNetValue, "DynamicNetValue.csv"); SaveArrayAsCSV_ <string>(trading_history_ETF, "ETFTradingHistoryforALL.csv"); Console.ReadKey(); }
protected override void chartSignal(Backtest.ProductBase product_, Controls.LineChartDataDisplay chart_) { chart_.AddSeries(product_.Prices, "Prices", 40, "##0.0##"); chart_.AddSeries(GenerateWeightSeries(product_, product_.Prices.Dates[0]), "Score", 80, "##0.0%"); }
protected override void chartSignal(Backtest.ProductBase product_, Controls.LineChartDataDisplay chart_) { //chart_.AddSeries(getPeriodReturns(product_.Prices), "NPeriodReturns", 80, "##0.0#%"); //chart_.AddSeries(getZScores(product_.Prices), "zScores", 80, "##0.0#"); chart_.AddSeries(GenerateWeightSeries(product_,null), "SignalScores", 80, "##0.0#"); }
public abstract void Chart(SI.Controls.LineChartDataDisplay lcdd_, Backtest.ProductBase product_);
public override DatedDataCollectionGen<double> GenerateWeightSeries(Backtest.ProductBase product_, DateTime? minDate_) { var cumultRet = product_.Prices.ToReturns(product_.Convention).ToCumulative(); var ma1 = HelperMethods.GetMA(cumultRet, MA1); var ma2 = HelperMethods.GetMA(cumultRet, MA2); var ma3 = HelperMethods.GetMA(cumultRet, MA3); var ks = HelperMethods.GetRollingStat(cumultRet, KWindow, HelperMethods.GetK); var turnoverThreshold = MinZScoreWinLength ?? 0d; if (product_ is Backtest.ProductFX && ((Backtest.ProductFX)product_).CoreProduct.IsGroup(Data.FXGroup.NDF)) turnoverThreshold = 0.35; //var ccy = ((Backtest.ProductFX) product_).CoreProduct; var scores = new List<double>(); for (int i = 0; i < ma3.Dates.Length; ++i) { var date = ma3.Dates[i]; //var cov = Singleton<SI.Data.CovarianceSource>.Instance.GetCovarianceForDateElesePrevious(date); var m1 = ma1.ValueOnExactDate(date); var m2 = ma2.ValueOnExactDate(date); var m3 = ma3.ValueOnExactDate(date); var k = ks.ValueOnDate(date); var v = cumultRet.ValueOnExactDate(date); var todayScore = 0d; //if (v > m1 && v > m2 && v > m3) //{ // todayScore = 0.1; // 1.0 //} //else if (v < m1 && v > m2 && v > m3) //{ // todayScore = 0.05; // 0.25 //} //else if (v < m1 && v < m2 && v > m3) //{ // todayScore = -0.05; // -0.25 //} //else if (v < m1 && v < m2 && v < m3) //{ // todayScore = -0.1; // -1.0 //} //else if (v > m1 && v < m2 && v < m3) //{ // todayScore = -0.05; // -0.25 //} //else if (v > m1 && v > m2 && v < m3) //{ // todayScore = 0.05; // 0.25 //} //else //{ // todayScore = 0.0; //} //if (todayScore > 0d && k < KCutoff) // todayScore = 0d; //if (todayScore < 0d && k > -KCutoff) // todayScore = 0d; if (v > m1 && v > m2 && v > m3 && k > KCutoff) todayScore = 0.1; else if (v < m1 && v > m2 && v > m3 && k > KCutoff) todayScore = 0.05; else if (v < m1 && v < m2 && v > m3 & k < -KCutoff) todayScore = -0.05; else if (v < m1 && v < m2 && v < m3 & k < -KCutoff) todayScore = -0.1; else todayScore = 0d; if (i < 100) { scores.Add(todayScore); continue; } var yestScore = scores.Last(); var shiftScore = Math.Abs(todayScore - yestScore); if (shiftScore > 0d) { // find the full period in which we've been in this score var index = scores.Count - 1; { while (index >= 0 && scores[index] == yestScore) { --index; } index = index + 1; // just move up to the first day that we had the same score as 'yestScore' } // get the cumulative return values in which we maintained the previous state var subValues = cumultRet.GetSubValues(ma3.Dates[index], ma3.Dates[i - 1]); // work out the maximum zScore during this period double zScoreUse; { var vol = product_.GetVol(date, Backtest.VolType.covar); var highRange = Math.Abs(v - subValues.Data.Max()); var lowRange = Math.Abs(v - subValues.Data.Min()); zScoreUse = Math.Max(highRange, lowRange)*Math.Sqrt(252)/(vol*1.65); } if (MinZScoreWinLength.HasValue && subValues.Length < MinZScoreWinLength.Value) { todayScore = yestScore; //Console.WriteLine(string.Format("{0}-{1}", date, zScoreUse)); } else if (zScoreUse < turnoverThreshold) todayScore = yestScore; } scores.Add(todayScore); } return new DatedDataCollectionGen<double>(ma3.Dates, scores.ToArray()); }
private static void TestStrategy005(decimal TPPercent, decimal SLPercent, int DaysToTimeout, double BuyLimit, double SellLimit) { var PredictionList = new List <Prediction>(); using (var ctx = new Db()) { int?strategyNr = ctx.Database.SqlQuery <int?>("select 1 + max (StrategyNr) from fact.predictions").FirstOrDefault(); var b = new Backtest { StrategyNr = strategyNr == null ? 0 : strategyNr.Value, TimeCalculated = DateTime.Now, TakeProfitPercent = TPPercent, StopLossPercent = SLPercent, DaysToTimeout = DaysToTimeout, SignalName = "Signal006", SellLimit = SellLimit, BuyLimit = BuyLimit, FromDate = new DateTime(2016, 12, 1), TillDate = new DateTime(2017, 1, 15), MinShingleSamples = 10, ShingleInterval = DaysToTimeout, Comment = $"Signal006 Buylimit:{BuyLimit:0.##} Selllimit:{SellLimit:0.##} " }; var orders = GetSignals006(10, BuyLimit, SellLimit, TPPercent, SLPercent, b.FromDate, b.TillDate); foreach (var ord in orders) { var lastTrade = ctx.Database.SqlQuery <DateTime?>("select max(TimeClose) from fact.predictions where Ticker = @ticker and StrategyNr = @nr", new SqlParameter("@ticker", ord.Ticker), new SqlParameter("@nr", b.StrategyNr)).FirstOrDefault(); if (lastTrade != null && lastTrade.Value >= ord.Issued) { continue; } Prediction t = Trade(ord.Direction, ord.Ticker, ord.Issued, b.TakeProfitPercent, b.StopLossPercent, b.Comment, DaysToTimeout, b.StrategyNr); if (t == null) { continue; } DisplayPrediction(t); PredictionList.Add(t); ctx.Predictions.Add(t); ctx.SaveChanges(); } if (PredictionList.Count > 0) { b.Wins = PredictionList.Count(x => x.Profit > 0); b.Loses = PredictionList.Count(x => x.Profit <= 0); b.Takeprofits = PredictionList.Count(x => x.Exit == ExitReason.TakeProfit); b.Stoploses = PredictionList.Count(x => x.Exit == ExitReason.StopLoss); b.Timeouts = PredictionList.Count(x => x.Exit == ExitReason.Timeout); b.Buys = PredictionList.Count(x => x.BuySignal); b.Sells = PredictionList.Count(x => !x.BuySignal); b.BuyProfit = PredictionList.Where(x => x.BuySignal).Select(x => x.Profit).Sum(); b.SellProfit = PredictionList.Where(x => !x.BuySignal).Select(x => x.Profit).Sum(); b.WinProfit = PredictionList.Where(x => x.Profit > 0).Select(x => x.Profit).Sum(); b.LossProfit = PredictionList.Where(x => x.Profit < 0).Select(x => x.Profit).Sum(); b.TimeoutProfit = PredictionList.Where(x => x.Exit == ExitReason.Timeout).Select(x => x.Profit).Sum(); b.AverageTradeLength = PredictionList.Select(x => (decimal)((x.TimeClose - x.TimeOpen).Days)).Average(); ctx.Backtests.Add(b); ctx.SaveChanges(); } } }
protected override void chartSignal(Backtest.ProductBase product_, Controls.LineChartDataDisplay chart_) { var cumultRet = product_.Prices.ToReturns(product_.Convention).ToCumulative(); var ma1 = HelperMethods.GetMA(cumultRet, MA1); var ma2 = HelperMethods.GetMA(cumultRet, MA2); var ma3 = HelperMethods.GetMA(cumultRet, MA3); var ks = HelperMethods.GetRollingStat(cumultRet, KWindow, HelperMethods.GetK); chart_.ClearSeries(); chart_.AddSeries(cumultRet, "Prices", 40, "##0.0##"); chart_.AddSeries(ma1, string.Format("MA({0})", MA1), 40, "##0.0##"); chart_.AddSeries(ma2, string.Format("MA({0})", MA2), 40, "##0.0##"); chart_.AddSeries(ma3, string.Format("MA({0})", MA3), 40, "##0.0##"); chart_.AddSeries(ks, string.Format("K({0})", KWindow), 80, "##0.0"); }