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);
		}
	}
}