| Overall Statistics |
|
Total Trades 28 Average Win 4.43% Average Loss -1.34% Compounding Annual Return 54.647% Drawdown 12.000% Expectancy 1.304 Net Profit 54.174% Sharpe Ratio 1.727 Loss Rate 46% Win Rate 54% Profit-Loss Ratio 3.30 Alpha 0.376 Beta 0.122 Annual Standard Deviation 0.223 Annual Variance 0.05 Information Ratio 1.285 Tracking Error 0.242 Treynor Ratio 3.149 Total Fees $1012.21 |
using System;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
using QuantConnect.Securities;
using QuantConnect.Models;
namespace QuantConnect {
public partial class SwingTraderPro : QCAlgorithm
{
//Initialize: Storage for our custom data:
//Source: http://www.wunderground.com/history/
//Make sure to link to the actual file download URL if using dropbox.
//private string url = "https://www.dropbox.com/s/txgqzv2vp5lzpqc/10065.csv";
private Signal yesterday;
private int rebalanceFrequency = 1, tradingDayCount = 0;
private const string Symbol = "USO";
decimal leverage = 1m;
private SimpleMovingAverage sma;
private SimpleMovingAverage smanow;
private SimpleMovingAverage[] ribbon;
///<summary>
/// Initialize our algorithm:
///</summary>
public override void Initialize()
{
SetStartDate(2014,7, 01);
SetEndDate(2015, 6, 30);
SetCash(100000);
AddSecurity(SecurityType.Equity, Symbol, Resolution.Minute, false, leverage, false);
SetRunMode(RunMode.Series);
AddData<Signal>("SignalStregth", Resolution.Minute);
// create a 15 day exponential moving average
sma = SMA(Symbol, 5, Resolution.Daily);
// create a 30 day exponential moving average
smanow = SMA(Symbol, 1, Resolution.Daily);
// note how we can easily define these indicators to receive hourly data
int ribbonCount = 7;
int ribbonInterval = 15*8;
ribbon = new SimpleMovingAverage[ribbonCount];
for(int i = 0; i < ribbonCount; i++)
{
ribbon[i] = SMA(Symbol, (i + 1)*ribbonInterval, Resolution.Hour);
}
}
//Save the instance of the weather.
public void OnData(Signal data)
{
yesterday = data;
}
///<summary>
/// When we have a new event trigger, buy some stock:
///</summary>
private DateTime previous;
public void OnData(TradeBars data)
{
// wait for our slow ema to fully initialize
if (!sma.IsReady) return;
// only once per day
if (previous.Date == data.Time.Date) return;
var holdings = Portfolio[Symbol].Quantity;
//Rebalance every 10 days:
if (tradingDayCount >= rebalanceFrequency)
{
if (yesterday != null) {
if ((yesterday.Sig1m > 0 && smanow > sma) || (yesterday.Sig1m < 0 && smanow < sma)){
if (yesterday.Sig7d > 0 && holdings <= 0 ){
SetHoldings(Symbol, 1.0);
tradingDayCount = 0;}
if (yesterday.Sig7d < 0 && holdings >= 0 ){
SetHoldings(Symbol, -1.0);
tradingDayCount = 0;}
}
else {
SetHoldings(Symbol, 0);
tradingDayCount = 0;
}
}
}
Plot(Symbol, "Price", data[Symbol].Price);
// easily plot indicators, the series name will be the name of the indicator
Plot(Symbol, smanow, sma);
previous = data.Time;
}
///<summary>
/// After each trading day
///</summary>
public override void OnEndOfDay() {
tradingDayCount++;
}
}
/// <summary>
/// Weather based rebalancing
/// </summary>
public class Signal : BaseData
{
public decimal Sig7d = 0;
public decimal Sig14d = 0;
public decimal Sig1m = 0;
public string errString = "";
public Signal()
{
this.Symbol = "SignalStregth";
}
public override string GetSource(SubscriptionDataConfig config, DateTime date, DataFeedEndpoint datafeed)
{
return "https://www.dropbox.com/s/46g0psa9fws031p/S%26P500_withoutnontradingsignaldates_01072014_01072015.csv?dl=1";
}
public override BaseData Reader(SubscriptionDataConfig config, string line, DateTime date, DataFeedEndpoint datafeed)
{
Signal signal = new Signal();
try {
string[] data = line.Split(',');
signal.Time = DateTime.Parse(data[0]).AddHours(20); // Make sure we only get this data AFTER trading day - don't want forward bias.
signal.Sig7d = Convert.ToDecimal(data[1]);
signal.Sig14d = Convert.ToDecimal(data[2]);
signal.Sig1m = Convert.ToDecimal(data[3]);
} catch (Exception err)
{
return null;
}
return signal;
}
}
}