Overall Statistics |
Total Trades 18 Average Win 1.45% Average Loss -0.70% Compounding Annual Return 0.059% Drawdown 6.700% Expectancy 0.027 Net Profit 0.104% Sharpe Ratio 0.043 Loss Rate 67% Win Rate 33% Profit-Loss Ratio 2.08 Alpha 0.003 Beta -0.002 Annual Standard Deviation 0.07 Annual Variance 0.005 Information Ratio -0.214 Tracking Error 0.15 Treynor Ratio -1.939 Total Fees $18.00 |
-no value-
using Accord.Statistics.Models.Markov; using Accord.Statistics.Models.Markov.Learning; namespace QuantConnect { /* * QuantConnect University: 50-10 EMA - Exponential Moving Average Cross * * The classic exponential moving average cross implementation using a custom class. * The algorithm uses allows for a safety margin so you can reduce the "bounciness" * of the trading to confirm the crossing. */ public enum TRADETYPE { LOSING, NEUTRAL, WINNING }; public class EMATest : QCAlgorithm { //Define required variables: int quantity = 0; decimal price = 0; decimal tolerance = 0m; //0.1% safety margin in prices to avoid bouncing. string symbol = "SPY"; DateTime sampledToday = DateTime.Now; List<decimal> _tradeReturns = new List<decimal>(); private const int MAXRETURNS = 4; //Set up the EMA Class: ExponentialMovingAverage emaShort; ExponentialMovingAverage emaLong; //Initialize the data and resolution you require for your strategy: public override void Initialize() { SetStartDate(2014, 01, 01); SetEndDate(DateTime.Now); SetCash(25000); AddSecurity(SecurityType.Equity, symbol, Resolution.Daily); emaShort = EMA(symbol, 10, Resolution.Daily); emaLong = EMA(symbol, 50, Resolution.Daily); for (int i = 0; i < MAXRETURNS; i++) { _tradeReturns.Add(0); } } public override void OnOrderEvent(OrderEvent orderEvent) { if (orderEvent.Status == OrderStatus.Filled && orderEvent.FillQuantity < 0) { SecurityHolding s = Securities [orderEvent.Symbol].Holdings; var profit_pct = s.LastTradeProfit / Portfolio.TotalPortfolioValue; _tradeReturns.Add (profit_pct); if (_tradeReturns.Count > MAXRETURNS) _tradeReturns.RemoveAt (0); } } //Handle TradeBar Events: a TradeBar occurs on every time-interval public void OnData(TradeBars data) { //One data point per day: if (sampledToday.Date == data[symbol].Time.Date) return; //Only take one data point per day (opening price) price = Securities[symbol].Close; sampledToday = data[symbol].Time; //Wait until EMA's are ready: if (!emaShort.IsReady || !emaLong.IsReady) return; //Get fresh cash balance: Set purchase quantity to equivalent 10% of portfolio. decimal cash = Portfolio.Cash; int holdings = Portfolio[symbol].Quantity; //quantity = Convert.ToInt32((cash * 0.5m) / price); if (holdings > 0) { //If we're long, or flat: check if EMA crossed negative: and crossed outside our safety margin: if ((emaShort * (1+tolerance)) < emaLong) { //Now go short: Short-EMA signals a negative turn: reverse holdings Order(symbol, -(holdings)); Log(Time.ToShortDateString() + " > Go Short > Holdings: " + holdings.ToString() + " Quantity:" + quantity.ToString() + " Samples: " + emaShort.Samples); } } else if (holdings == 0) { //If we're short, or flat: check if EMA crossed positive: and crossed outside our safety margin: if ((emaShort * (1 - tolerance)) > emaLong) { //Now go long: Short-EMA crossed above long-EMA by sufficient margin var quantity = GetNumSymbols(price); Order(symbol, Math.Abs(holdings) + quantity); Log(Time.ToShortDateString() + "> Go Long > Holdings: " + holdings.ToString() + " Quantity:" + quantity.ToString() + " Samples: " + emaShort.Samples); } } } private TRADETYPE PredictNextTrade() { var res = TRADETYPE.WINNING; if (_tradeReturns.Count == 4) { HiddenMarkovModel hmm = new HiddenMarkovModel(states: 3, symbols: 3); int[] observationSequence = GetSequence (_tradeReturns); BaumWelchLearning teacher = new BaumWelchLearning(hmm); // and call its Run method to start learning double error = teacher.Run(observationSequence); int[] predict = hmm.Predict (observationSequence, 1); if (predict [0] == 0) { res = TRADETYPE.LOSING; } else if (predict [0] == 1) { res = TRADETYPE.NEUTRAL; } else if (predict [0] == 2) { res = TRADETYPE.WINNING; } } return res; } private int[] GetSequence(List<decimal> returns) { int[] observationSequence = new int[4]; for(int i=0;i<returns.Count;i++) { if (returns [i] < 0m) observationSequence [i] = 0; // loss else if (returns [i] > 0m && returns [i] < 0.01m) observationSequence [i] = 1; //neutral, small win else observationSequence [i] = 2; //big win }; return observationSequence; } private int GetNumSymbols(decimal currentPrice) { var direction = PredictNextTrade (); var predict_risk = 1.0m; switch (direction) { case TRADETYPE.LOSING: predict_risk = 0.5m; break; case TRADETYPE.NEUTRAL: predict_risk = 0.8m; break; } var quantity = (int)(Math.Round (predict_risk* Portfolio.Cash/currentPrice)); return quantity; } } }