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