Overall Statistics |
Total Trades 51 Average Win 0.21% Average Loss -0.24% Compounding Annual Return -1.018% Drawdown 9.000% Expectancy -0.655 Net Profit -1.121% Sharpe Ratio -0.071 Loss Rate 82% Win Rate 18% Profit-Loss Ratio 0.90 Alpha -0.031 Beta 0.348 Annual Standard Deviation 0.076 Annual Variance 0.006 Information Ratio -0.773 Tracking Error 0.103 Treynor Ratio -0.016 Total Fees $51.00 |
using System; using System.Collections.Concurrent; using System.Linq; using QuantConnect.Data.Market; using QuantConnect.Data.UniverseSelection; using QuantConnect.Indicators; namespace QuantConnect.Algorithm.CSharp { // mittelwert_neu = mittelwert_bisher - (mittelwert_bisher - neuer_wert)/anzahl_werte /// <summary> /// tbd /// </summary> public class UW_Simplify_V3 : QCAlgorithm { private Symbol _spy = QuantConnect.Symbol.Create("SPY", SecurityType.Equity, Market.USA); private SecurityChanges _changes = SecurityChanges.None; private DateTime TestDate = new DateTime(2016,10,22); //private readonly Dictionary<Symbol, SymbolData> Data = new Dictionary<Symbol, SymbolData>(); // holds our coarse fundamental indicators by symbol private readonly ConcurrentDictionary<Symbol, SelectionData> _averages = new ConcurrentDictionary<Symbol, SelectionData>(); const decimal Tolerance = 0.01m; private const int Count = 30; private const decimal TargetPercent = 0.1m; private const decimal tpPercent = 0.05m; Dictionary<Symbol, SymbolData> MySymbolData = new Dictionary<Symbol, SymbolData>(); // class used to improve readability of the coarse selection function private class SelectionData { public readonly ExponentialMovingAverage Fast; public readonly ExponentialMovingAverage Slow; public readonly ExponentialMovingAverage Slowest; public SelectionData() { Fast = new ExponentialMovingAverage(20); Slow = new ExponentialMovingAverage(30); Slowest = new ExponentialMovingAverage(100); } // computes an object score of how much large the fast is than the slow public decimal ScaledDelta { get { return (Fast - Slow)/((Fast + Slow)/2m); } } // updates the EMA50 and EMA100 indicators, returning true when they're both ready public bool Update(DateTime time, decimal value) { return Fast.Update(time, value) && Slow.Update(time, value) && Slowest.Update(time, value); } } /// <summary> /// Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized. /// </summary> public override void Initialize() { SetStartDate(2015, 10, 07); //Set Start Date SetEndDate(2016, 11, 11); //Set End Date SetCash(25000); //Set Strategy Cash // AddEquity("SPY", Resolution.Daily); UniverseSettings.Resolution = Resolution.Daily; AddUniverse(coarse => { return (from cf in coarse // grab th SelectionData instance for this symbol let avg = _averages.GetOrAdd(cf.Symbol, sym => new SelectionData()) // Update returns true when the indicators are ready, so don't accept until they are where avg.Update(cf.EndTime, cf.Price) // only pick symbols who have their price over their 200 day ema where cf.Price > avg.Slowest // only pick symbols who have their 50 day ema over their 200 day ema where avg.Slow > avg.Slowest // only pick symbols who have their 20 day ema over their 20 day ema where avg.Fast> avg.Slow // prefer symbols with a larger delta by percentage between the two averages orderby avg.ScaledDelta descending // we only need to return the symbol and return 'Count' symbols select cf.Symbol).Take(Count); }); Debug(" End Init"); foreach (var added in _changes.AddedSecurities) { if (!MySymbolData.ContainsKey(added.Symbol)) { MySymbolData.Add(added.Symbol, new SymbolData(added.Symbol, this)); Debug(" in Init added " + added.Symbol); } } } // end Initialize /// <summary> /// OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here. /// </summary> /// <param name="data">Slice object keyed by symbol containing the stock data</param> public override void OnData(Slice data) { if (!Portfolio.Invested) { SetHoldings(_spy, 1); Debug("Purchased Stock"); } if (_changes == SecurityChanges.None) return; foreach (var Stock in MySymbolData.Values) { if (data.ContainsKey(Stock.Symbol)) return; if (IsWarmingUp) return; // Stock.Update(Stock.Security, Stock.Security.Time); // Stock.lSMA.Update(data.EndTime, data.Close); Debug(" >> " + Stock.Security + " " + Stock.Security.Price + " " + Stock.hSMA + " " + Stock.lSMA); if ( Portfolio.Count < 5) { if ( Stock.Security.Price > Stock.hSMA ) { Log("BUY >> " + Stock.Security.Price); Debug("BUY >> " + Stock.Security.Price); SetHoldings(Stock.Symbol, 0.5m); var takeProfit = Stock.Security.Price*tpPercent; LimitOrder(Stock.Symbol, - Stock.Quantity, takeProfit); } if (Stock.Quantity > 0 && Stock.Security.Price <= Stock.lSMA) { Log("SELL >> " + Stock.Security.Price); Debug("SELL >> " + Stock.Security.Price); Liquidate(Stock.Symbol); } } } // liquidate securities removed from our universe foreach (var security in _changes.RemovedSecurities) { if (security.Invested) { Liquidate(security.Symbol); } } // we'll simply go long each security we added to the universe foreach (var security in _changes.AddedSecurities) { SetHoldings(security.Symbol, 1); } foreach (var security in _changes.AddedSecurities) { if (Time.Date == new DateTime(2016,10,13) ) Debug("1 Symbol= " + Time.ToShortDateString() + " " + security.Symbol.ToString() + " " ); } } // end OnData public override void OnSecuritiesChanged(SecurityChanges changes) { _changes = changes; Debug(Time.Date.ToShortDateString() + " 2 Number=" + _changes.AddedSecurities.Count.ToString() ); foreach (var security in _changes.AddedSecurities) { Debug("Added " + security.Symbol); if (!MySymbolData.ContainsKey(security.Symbol)) { MySymbolData.Add(security.Symbol, new SymbolData(security.Symbol, this)); Debug("Added to Data -> " + security.Symbol); } } foreach (var security in _changes.RemovedSecurities) { Debug("Removed " + security.Symbol); } } // end OnSecuritiesChanged } // end class /* You will need to create a class similar to SelectionData, say SymbolData, and create a dictionary to hold its values Dictionary<Symbol, SymbolData> to save the SMA of High and Low to be used as trading signal. */ class SymbolData { public string Symbol; private const int hPeriods = 8; public int rollingWindowSize = 1; public readonly Security Security; public int Quantity { get { return (int)Security.Holdings.Quantity; } } public readonly Identity Close; public readonly SimpleMovingAverage hSMA; public readonly SimpleMovingAverage lSMA; public readonly RollingWindow<TradeBar> lastDay; public SymbolData(string symbol, QCAlgorithm algorithm) { Symbol = symbol; Security = algorithm.Securities[symbol]; Close = algorithm.Identity(symbol); hSMA = algorithm.SMA(symbol, hPeriods, Resolution.Daily, Field.High); lSMA = algorithm.SMA(symbol, hPeriods, Resolution.Daily, Field.Low); lastDay = new RollingWindow<TradeBar>(rollingWindowSize);; } public bool Update(CoarseFundamental coarse) { lSMA.Update(coarse.EndTime, coarse.Value); return hSMA.Update(coarse.EndTime, coarse.Value ); } public bool IsReady { get { return Close.IsReady && hSMA.IsReady && lSMA.IsReady && lastDay.IsReady; } } } // end class } // end namespace