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