Overall Statistics |
Total Trades 192 Average Win 0.76% Average Loss -0.37% Compounding Annual Return 7.96% Drawdown 3.800% Expectancy 0.27 Net Profit 20.574% Sharpe Ratio 1.409 Loss Rate 58% Win Rate 42% Profit-Loss Ratio 2.05 Alpha 0.037 Beta 0.222 Annual Standard Deviation 0.055 Annual Variance 0.003 Information Ratio -1.06 Tracking Error 0.101 Treynor Ratio 0.351 Total Fees $384.00 |
using System; using System.Collections.Generic; using QuantConnect.Data.Consolidators; using QuantConnect.Indicators; using QuantConnect.Data.Market; using Accord.MachineLearning.VectorMachines; using Accord.MachineLearning.VectorMachines.Learning; namespace QuantConnect.Algorithm { /* * QuantConnect University: FOREX - Using Currency Data * * QuantConnect allows you to use currency data for your backtest with a * simple line of code. See the SecurityType.Forex below. */ public class ExampleMachineLearning : QCAlgorithm { static int trainSize = 30; static int inputSize = 3; static decimal stopPct = 0.4m; static decimal tradePct = 1.0m; string _symbol = "SPY"; decimal stopPrice; RollingWindow<TradeBar> _daywindow = new RollingWindow<TradeBar>(inputSize*trainSize+2); AverageTrueRange _atr; Queue<double[]> _samples = new Queue<double[]>(trainSize); SupportVectorMachine svm; /// <summary> /// Initialize QuantConnect Strategy. /// </summary> public override void Initialize() { SetStartDate(2013, 1, 1); SetEndDate(DateTime.Now.Date.AddDays(-1)); SetCash(10000); AddSecurity(SecurityType.Equity, _symbol, Resolution.Minute); _atr = ATR(_symbol, 20, MovingAverageType.Simple, Resolution.Daily); // Construct Day Consolidator var dayConsolidator = new TradeBarConsolidator(TimeSpan.FromDays(1)); dayConsolidator.DataConsolidated += OnDataDay; SubscriptionManager.AddConsolidator(_symbol, dayConsolidator); } /// <summary> /// OnData Callback (called every minute) - Prediction is made once per day, 1m after market opens /// StopLoss is handled on a minutely basis. /// </summary> public void OnData(TradeBars data) { // Wait for data to become ready if (!_atr.IsReady) return; if (!_daywindow.IsReady) return; // At Market Open use historical close data to make a prediction if ( (data.Time.Hour == 9) && (data.Time.Minute == 31)) { double[] returns = new double[inputSize]; int[] _targets = new int[trainSize]; // Build training set from historical data _samples.Clear(); for (int i=0;i<trainSize;i++) { for (int j=0;j<inputSize;j++) { returns[j] = (((_daywindow [i+j+1].Close - _daywindow[i+j+2].Close) / _daywindow[i+j+2].Close) > 0) ? 1 : -1; } _targets[i] = (((_daywindow [i].Close - _daywindow[i+1].Close) / _daywindow[i+1].Close) > 0) ? 1 : -1; _samples.Enqueue(returns); } double[][] inputs = _samples.ToArray(); Debug("Training..."); // instantiate new Support Vector Machine svm = new SupportVectorMachine(inputs: inputSize); // train SupportVectorMachine var teacher = new LinearCoordinateDescent(svm, inputs, _targets); teacher.Run(); // Get the most current inputs and make a prediction double[] _curInputs = new double[inputSize]; for (int i=0;i<inputSize;i++) { _curInputs[i] = (((_daywindow [i].Close - _daywindow[i+1].Close) / _daywindow[i+1].Close) > 0) ? 1 : -1; } double output = svm.Compute(_curInputs); Debug ("Prediction: " + output); if (output > 0) { // update stoploss stopPrice = data[_symbol].Close - stopPct * _atr; // Go Long if (Securities [_symbol].Holdings.Quantity == 0) { Order(_symbol, Portfolio.TotalPortfolioValue/data[_symbol].Close*tradePct); Debug ("Buy Shares: " + Securities [_symbol].Holdings.Quantity); } else if (Securities [_symbol].Holdings.Quantity < 0){ // if we are in a short position: calculate how many shares needed to go long Order(_symbol, ((decimal)-Securities[_symbol].Holdings.Quantity)+(Portfolio.TotalPortfolioValue/data[_symbol].Close*tradePct)); Debug ("Buy Shares: " + Securities [_symbol].Holdings.Quantity); } } else { // Exit Market Liquidate(_symbol); Debug ("Exiting Market"); } } // Handle Stop Loss if (Securities [_symbol].Holdings.Quantity != 0) { if (Securities[_symbol].Holdings.IsLong) { if (data[_symbol].Low <= stopPrice) { Liquidate(_symbol); Debug ("Hit StopLoss: " + data[_symbol].Low); } } if (Securities [_symbol].Holdings.IsShort) { if (data[_symbol].High >= stopPrice) { Liquidate(_symbol); Debug ("Hit StopLoss: " + data[_symbol].High); } } } } /// <summary> /// OnDataDay Callback (called every day) - Used to build the daily history (rolling window) of close prices /// </summary> private void OnDataDay(object sender, TradeBar consolidated) { //Inject data into the rolling window. _daywindow.Add(consolidated); } } }