Overall Statistics
Total Trades
134
Average Win
0.21%
Average Loss
-0.07%
Compounding Annual Return
1319.775%
Drawdown
0.900%
Expectancy
1.370
Net Profit
6.793%
Sharpe Ratio
10.879
Loss Rate
40%
Win Rate
60%
Profit-Loss Ratio
2.97
Alpha
1.629
Beta
0.403
Annual Standard Deviation
0.154
Annual Variance
0.024
Information Ratio
10.149
Tracking Error
0.154
Treynor Ratio
4.153
Total Fees
$5.26
using System;
using System.Linq;
using QuantConnect.Data.Market;
using QuantConnect.Indicators;
using System.Drawing;


namespace QuantConnect.Algorithm.CSharp
{
    public class BasicTemplateAlgorithm : QCAlgorithm
    {
        private string _sym = QuantConnect.Symbol.Create("BTCUSD", SecurityType.Crypto, Market.GDAX);
        private List<OrderTicket> _openLimitOrders = new List<OrderTicket>();
        private RollingWindow<TradeBar> History = new RollingWindow<TradeBar>(5);
        private decimal at_risk_amount = 2000;
        private decimal target_exit_price = 0.0m;
        private decimal target_cover_price = 0.0m;
        private decimal buy_back_amount = 0.0m;
        private RelativeStrengthIndex rsi_now;
        private AbsolutePriceOscillator apo_now;
        private AverageTrueRange atr_now;
        private bool go_long = false;
        private bool go_short = false;
        private int frequency = 2;
        private int entry_counter = 260/2;
        private int exit_counter = 36000/2;
        private bool in_trade_long = false;
        private bool in_trade_short = false;
        private bool stop_set = false;
        private decimal target_stop_price = 0.0m;
        private decimal current_price = 0.0m;
        private decimal entry_point_long = 0.0m;
        private decimal entry_point_short = 0.0m;
        private decimal entry_point_amount = 0.0m;
        private decimal previous_equity = 0.0m;
        private decimal windfall_measure = 0.0m;

        public override void Initialize()
        {
        	Debug("Init");
        	SetBrokerageModel(BrokerageName.GDAX, AccountType.Cash);
            DateTime dt = new DateTime(2017, 11, 1, 12, 2, 7, 0);
            SetStartDate(dt);  //Set Start Date
            DateTime dt1 = new DateTime(2017, 11, 9, 12, 4, 7, 0);
            SetEndDate(dt1);  //Set Start Date
            //SetEndDate(DateTime.Now);
            AddCrypto("BTCUSD", Resolution.Second, Market.GDAX);
            SetCash(at_risk_amount);
            Debug("Basic Setup completed");
            
            //every second for order timeframe
            var consolidator = new TradeBarConsolidator(frequency);
			consolidator.DataConsolidated += OrderHandler;
			SubscriptionManager.AddConsolidator("BTCUSD", consolidator);
			Debug("Consolidator 1 added...");
			
			//every five minutes for indicator timeframe
			var consolidator2 = new TradeBarConsolidator(5*60);
			consolidator2.DataConsolidated += DecisionHandler;
			var consolidator3 = new TradeBarConsolidator(15*60);
			//consolidator3.DataConsolidated += StopHandler;
			rsi_now = RSI("BTCUSD", 14, MovingAverageType.Simple);
			apo_now = APO("BTCUSD", 12, 26, MovingAverageType.Exponential);
			atr_now = ATR("BTCUSD", 14, MovingAverageType.Simple);
			RegisterIndicator("BTCUSD", rsi_now, consolidator2);
			RegisterIndicator("BTCUSD", apo_now, consolidator2);
			SubscriptionManager.AddConsolidator("BTCUSD", consolidator2);
			Debug("Consolidator 2 added...");
			//SubscriptionManager.AddConsolidator("BTCUSD", consolidator3);
			//Debug("Consolidator 3 added...");
			//set sold to true, to trigger first trade in buy direction
			
			Chart plotter = new Chart("Plotter");
            plotter.AddSeries(new Series("Price", SeriesType.Line, index:0));
            //plotter.AddSeries(new Series("RSI", SeriesType.Line, index:0));
            //plotter.AddSeries(new Series("APO", SeriesType.Line, index:0));
            plotter.AddSeries(new Series("Buy", SeriesType.Scatter, string.Empty, Color.Green, ScatterMarkerSymbol.Triangle));
            plotter.AddSeries(new Series("Sell", SeriesType.Scatter, string.Empty, Color.Red, ScatterMarkerSymbol.TriangleDown));
            AddChart(plotter);
            
        }
        
        
        private void DecisionHandler(object sender, BaseData consolidated2)
        {
        	//Debug("Price: " + consolidated2.Price);
        	Plot("Plotter", "Price", consolidated2.Price);
        	
        	if(!rsi_now.IsReady) return;
        	if(!apo_now.IsReady) return;
        	
        	if (rsi_now.Current.Value > 50 
        	&& rsi_now.Current.Value < 70
        	&& apo_now.Current.Value > 0 
        	&& !in_trade_long && !in_trade_short)
        	//isRisingRSI(rsi_now) )
            {
            	Log("LONG Trigger. Price: " + consolidated2.Price);
            	go_long = true;
            }

            
            Debug("APO: " + apo_now.Current.Value);
            
            //if(in_trade_long)https://www.quantconnect.com/terminal/#
            // 	Debug("IN TRADE: Long");
            //if(in_trade_short)
            //	Debug("IN TRADE: Short");
            	
            Debug("BTC Holdings in USD: $" + Convert.ToString(Portfolio.CashBook["BTC"].ValueInAccountCurrency));
            Debug("BTC Holdings in BTC: B" + Convert.ToString(Portfolio.CashBook["BTC"].ValueInAccountCurrency / consolidated2.Price));
            Debug("Equity in USD: $" + Convert.ToString(Portfolio.Cash));

        }
        

        

        private void OrderHandler(object sender, BaseData consolidated)
        {
        	//Plot(_sym, "Price", consolidated.Price);
        	//Debug("Price: " + consolidated.Price);
        	
            if(go_long)
            {
            	decimal amnt = Math.Round(Portfolio.Cash / consolidated.Price, 4);
            	ExecuteLimitOrder("BTCUSD", amnt, Math.Round((decimal)consolidated.Price,2), "buy");
            	entry_point_long = (decimal)consolidated.Price;
            	entry_point_amount = amnt;
            }
            if(in_trade_long)
            {
	            if(previous_equity > 0){
	            	var diff =  Portfolio.Cash - previous_equity;
	            	//Debug("Diff: " + diff);
	            	//Debug("Pre: " + previous_equity);
	            	windfall_measure = (diff / previous_equity) * 100;
	            	//Debug(windfall_measure.ToString());
	            }
	            //Debug("Equity increase: " + windfall_measure);
	            
            	current_price = consolidated.Price;
            	decimal amnt = entry_point_amount;
            	ExecuteLimitOrder("BTCUSD", amnt, target_exit_price, "sell");
            }



        }
        
        /*
        Will trigger limit order, adjust price to 
        */
        private decimal ExecuteLimitOrder(string symbol, decimal amnt, decimal price, string direction)
        {
        	if(in_trade_long && windfall_measure > 0.5m){
					Debug("WINDFALL ALERT - get out now!");
	        		Transactions.CancelOpenOrders("BTCUSD");
	        		Debug("AReset counters...Timeout");
	        		go_long = false;
	        		go_short = false;
	        		in_trade_long= false;
	        		in_trade_short= false;
	        		entry_counter = 260/frequency;
					Liquidate("BTCUSD");
					return 0.0m;
			}
        	if(entry_counter == 0){
        		Transactions.CancelOpenOrders("BTCUSD");
        		Debug("AReset counters...Timeout");
        		go_long = false;
        		go_short = false;
        		in_trade_long= false;
        		in_trade_short= false;
        		entry_counter = 260/frequency;
        		return 0.0m;
        	}
        	if(exit_counter == 0)
        	{
        		//Either drop what you have if we are positive and reset that way
				//or... emergency stop.
				if(in_trade_long && current_price > entry_point_long){
					Debug("Liquidating...");
					Liquidate("BTCUSD");
				}
				else{
					Debug("Current Price: " + current_price);
					Debug("Entry Point Long: " + entry_point_long);
					Debug("Entry Point Short: " + entry_point_short);
					Debug("LONG: " + in_trade_long);
					Debug("SHORT: " + in_trade_short);
					Quit(); //Option: Instruct algorithm to stop.
				}
				
        		Transactions.CancelOpenOrders("BTCUSD");
        		Debug("BReset counters...Timeout");
        		go_long = false;
        		go_short = false;
        		in_trade_long= false;
        		in_trade_short= false;
        		exit_counter = 36000/frequency;
        		Debug("We are stuck - no exit was possible. Why???");
        		Debug("Could not exit in given time. Halting algorithm.");
			
        		return 0.0m;
        	}
        	//Debug("Order Handler");
        	List<Order> myOrders = Transactions.GetOpenOrders("BTCUSD");
        	if (myOrders.Count <= 0)
            {
	        	//Debug(Time.ToString() + " Submitting LimitOrder");
	            if(direction == "sell"){
	            	Debug("Let's sell...");
		            LimitOrder("BTCUSD", -1*amnt, price + 0.01m);
		            Debug(Time.ToString() + " Amount: " + -1*amnt);
		            Debug(Time.ToString() + " Price: " + (price + 0.01m));
	            	if(in_trade_long || in_trade_short) 
	            		exit_counter--;
	            	else
	            		entry_counter--;
	            	
	            	Debug("EntryCounter: " + entry_counter);
        			Debug("ExitCounter: " + exit_counter);

	            }
	            else if (direction == "buy"){
	            	if(go_long) Debug("Let's buy..."); else Debug("Let's cover");
	            	LimitOrder("BTCUSD", amnt, price - 0.01m);
	            	Debug(Time.ToString() + " Amount: " + amnt);
	            	Debug(Time.ToString() + " Price: " + (price - 0.01m));
	            	if(in_trade_long || in_trade_short)  
	            		exit_counter--;
	            	else
	            		entry_counter--;
	            		
	            	Debug("EntryCounter: " + entry_counter);
        			Debug("ExitCounter: " + exit_counter);
        			
	            }
	        }
	        else
	        {
	        	if(in_trade_long || in_trade_short)  exit_counter--; else entry_counter--;
	            		
                if(exit_counter < (36000/frequency) && exit_counter % 10 == 0){
                	if(in_trade_long &&  current_price < target_stop_price ){
                		Debug("STOP TRIGGERED - Get out of LONG");
                		Transactions.CancelOpenOrders("BTCUSD");
                		LimitOrder("BTCUSD", -1*amnt, current_price + 0.01m);
                	}
                }
	        }
	        return 0.0m;
        }
        
        public override void OnOrderEvent(OrderEvent orderEvent)
		{
		    var order = Transactions.GetOrderById(orderEvent.OrderId);
		    Debug(Time + ": " + order.Type + " - " + orderEvent);
		    if(orderEvent.Status == OrderStatus.Filled)
		    {
		    	if(order.Direction.ToString() == "Buy")
		    		Plot("Plotter", "Buy", orderEvent.FillPrice);
		    	else
		    		Plot("Plotter", "Sell", orderEvent.FillPrice);
		    		
		    	Debug("Order got filled: " + orderEvent.OrderId);
		    	Debug("EntryCounter: " + entry_counter);
        		Debug("ExitCounter: " + exit_counter);
		    	
		    	if(go_long && entry_counter < (260/frequency)){
		    		in_trade_long = true;
		    		go_long = false;
		    		target_exit_price = orderEvent.FillPrice + 10m;
		    		target_stop_price = orderEvent.FillPrice - atr_now.Current.Value;
		    		Debug("Exit Stop Price: " + target_stop_price);
		    		Debug("Exit Target Price: " + target_exit_price);
		    		entry_point_amount = orderEvent.FillQuantity;
		    		previous_equity = Portfolio.Cash;
		    	}
		    	if(in_trade_long && exit_counter < (36000/frequency)){
		    		in_trade_long = false;
		    		go_long = false;
            		Debug("Closed LONG - NOT IN TRADE");
		    	}
		    	
		    	if(in_trade_short && exit_counter < (36000/frequency)){
		    		in_trade_short = false;
		    		go_short = false;
		    		Debug("Covered SHORT - NOT IN TRADE");
		    	}
		    	
		    	Debug("Reset counters...2");
		    	entry_counter = 260/frequency;
                exit_counter = 36000/frequency;
		    	
		    }
		    
		}
    }
}