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