Overall Statistics
Total Trades
18
Average Win
13.03%
Average Loss
-2.36%
Compounding Annual Return
101.936%
Drawdown
51.300%
Expectancy
3.885
Net Profit
78.181%
Sharpe Ratio
2.323
Loss Rate
25%
Win Rate
75%
Profit-Loss Ratio
5.51
Alpha
-0.015
Beta
37.999
Annual Standard Deviation
0.219
Annual Variance
0.048
Information Ratio
2.26
Tracking Error
0.219
Treynor Ratio
0.013
Total Fees
$63.36
namespace QuantConnect.Algorithm.CSharp
{
    
    public class ARCryptoTemplateAlgorithm : QCAlgorithm
    {
    	// USER variables
        private string ticker = "BTCUSD";
		private int startingCash = 2000;
		private int maxPosition = 1000;
        private int minPosition = 500;
        private decimal usd;
        // PROGRAM variables
        public decimal price;
        public decimal holding;   // the # of eth that we hold in the portfolio
        public string baseSymbol; // "ETH"
        
        Stochastic sto;
        Resolution res = Resolution.Tick;
        RollingWindow<IndicatorDataPoint> stochKWin;
        RollingWindow<IndicatorDataPoint> stochDWin;
        
        Stochastic sto2;
        RollingWindow<IndicatorDataPoint> stochKWin2;
        RollingWindow<IndicatorDataPoint> stochDWin2;
        
        MovingAverageConvergenceDivergence macd;
        RollingWindow<IndicatorDataPoint> macdWin;
        MomersionIndicator momersion;
        
		
        public override void Initialize()
        {
            SetStartDate(2017, 3, 8);  //Set Start Date
            SetEndDate(2018, 1, 1);    //Set End Date
            SetCash(startingCash);    //Set Strategy Cash
			
            
            var crypto = AddCrypto(ticker, res);
            baseSymbol = crypto.BaseCurrencySymbol;
			SetBrokerageModel(BrokerageName.GDAX, AccountType.Cash);
			DefaultOrderProperties = new GDAXOrderProperties { PostOnly = true };
			
            Chart tradePlotter = new Chart("Trades");
            tradePlotter.AddSeries(new Series("BUY", SeriesType.Scatter, index:0));
            tradePlotter.AddSeries(new Series("SELL", SeriesType.Scatter, index:0));
            AddChart(tradePlotter);
            
            Chart stoPlotter = new Chart("Sto", ChartType.Stacked);
            stoPlotter.AddSeries(new Series("K", SeriesType.Line, index:0));
            //stoPlotter.AddSeries(new Series("D", SeriesType.Line, index:0));
            AddChart(stoPlotter);
            
            var consolidator = new TickConsolidator(3000);
            consolidator.DataConsolidated += consHandler;
            SubscriptionManager.AddConsolidator(ticker, consolidator);
            
            
            sto = new Stochastic(ticker, 10, 8, 3);
            RegisterIndicator(ticker, sto, consolidator);
            sto.StochK.Updated += (sender, updated) => stochKWin.Add(updated);
            sto.StochD.Updated += (sender, updated) => stochDWin.Add(updated);
            stochKWin = new RollingWindow<IndicatorDataPoint>(5);
            stochDWin = new RollingWindow<IndicatorDataPoint>(5);
            
            
            macd = new MovingAverageConvergenceDivergence(ticker, 3,8,9, MovingAverageType.Exponential);
            RegisterIndicator(ticker, macd, consolidator, x => x.Value);
            macd.Signal.Updated += (sender, updated) => macdWin.Add(updated);
            macdWin = new RollingWindow<IndicatorDataPoint>(5);
            
            // momersion = MOMERSION(ticker, 12,26);
            // RegisterIndicator(ticker, momersion, consolidator, x => x.Value);
            
            //--- minutely data consolidator
            var consolidator2 = new TickConsolidator(TimeSpan.FromMinutes(60));
            consolidator2.DataConsolidated += (sender, data) => { Log($"###### Time = {data.EndTime}");};
            SubscriptionManager.AddConsolidator(ticker, consolidator2);
            
            
            sto2 = new Stochastic(ticker, 14, 10, 5);
            RegisterIndicator(ticker, sto2, consolidator2);
            sto2.StochK.Updated += (sender, updated) => stochKWin2.Add(updated);
            sto2.StochD.Updated += (sender, updated) => stochDWin2.Add(updated);
            stochKWin2 = new RollingWindow<IndicatorDataPoint>(5);
            stochDWin2 = new RollingWindow<IndicatorDataPoint>(5);
        
        }

       
        //public override void OnData(Slice data)
        public void consHandler(object sender, TradeBar data)
        {
        	//price = data[ticker].Price;
        	price = data.Price;
        	usd = Portfolio.CashBook["USD"].Amount;
        	
        	Plot("Sto", "K", stochKWin[0]);
        	//Plot("Sto", "D", stochDWin[0]);
        	if (!stochKWin.IsReady && !stochDWin.IsReady && !macdWin.IsReady && !stochKWin2.IsReady && !stochDWin2.IsReady) {return;}
        	Log($"{price} at {data.EndTime}, K= {stochKWin[0].Value}, K2= {stochKWin2[0].Value}, MACD= {macdWin[0].Value}");
            if (!Portfolio.Invested && usd > minPosition)
            {
            	if (stochKWin[0].Value >= 20 && (stochKWin[1].Value < 20 || stochKWin[2].Value < 20 || stochKWin[3].Value < 20 ) && stochKWin[0].Value>stochDWin[0].Value && stochKWin2[0].Value >= 20 && stochKWin2[0].Value>stochDWin2[0].Value)//&& macdWin[0].Value>macdWin[1].Value)
            	{
            		decimal quantity = Math.Round(Math.Min(usd, maxPosition)/price,2);
                	LimitOrder(ticker, quantity, Math.Round((price - 0.01m),2));
                	Plot("Trades", "BUY", price);
            	}
            	
            }
            if (Portfolio.Invested)
            {
            	if (stochKWin[0] < 80 && stochKWin[1]>=80 && stochKWin[0] < stochDWin[0] && stochKWin2[0] < 80 && stochKWin2[1]>=80 && stochKWin2[0] < stochDWin2[0])
            	{
	            	holding = Portfolio.CashBook[baseSymbol].Amount;
	                MarketOrder(ticker, -holding);
	                Plot("Trades", "SELL", price);
            	}
            }
        }
        public override void OnOrderEvent(OrderEvent orderEvent){
        	Log(orderEvent.ToString());
        }
    }
}