Overall Statistics |
Total Trades 66 Average Win 0.92% Average Loss -1.65% Compounding Annual Return -95.460% Drawdown 25.300% Expectancy -0.481 Net Profit -21.782% Sharpe Ratio -3.133 Loss Rate 67% Win Rate 33% Profit-Loss Ratio 0.56 Alpha -1.167 Beta 1.439 Annual Standard Deviation 0.727 Annual Variance 0.528 Information Ratio -2.223 Tracking Error 0.677 Treynor Ratio -1.583 Total Fees $17.25 |
using QuantConnect.Securities.Option; namespace QuantConnect { public class StraddleFundamentalAlgorithm : QCAlgorithm { private List<Symbol> _symbols = new List<Symbol>(); private SecurityChanges _changes = SecurityChanges.None; private decimal TP = 0.125M; private decimal SL = -0.095M; public override void Initialize() { UniverseSettings.Resolution = Resolution.Daily; SetStartDate(2016, 01, 01); SetEndDate(2016, 01, 29); SetCash(10000); AddUniverse(CoarseSelectionFunction, FineSelectionFunction); } public IEnumerable<Symbol> CoarseSelectionFunction(IEnumerable<CoarseFundamental> coarse) { return coarse .Where(x => x.HasFundamentalData) .OrderByDescending(x => x.DollarVolume) .Select(x => x.Symbol).Take(10); } public IEnumerable<Symbol> FineSelectionFunction(IEnumerable<FineFundamental> fine) { return fine .Where(x => Time >= x.EarningReports.FileDate.AddDays(-9) && Time >= x.EarningReports.FileDate.AddDays(0) && x.EarningReports.FileDate != new DateTime()) .Select(x => x.Symbol).Take(5); } public override void OnData(Slice data) { List<Symbol> hSymbols = new List<Symbol>(); List<SecurityHolding> hHoldings = new List<SecurityHolding>(); int i = 0; foreach (var kvp in Portfolio) { var holdingSymbol = kvp.Key; var holdings = kvp.Value; if (holdings.AbsoluteQuantity > 0) { hSymbols.Add(holdingSymbol); hHoldings.Add(holdings); } } int y = 0; decimal totalPercent = 0; foreach(Symbol holdingSymbol in hSymbols){ if (y == 0){ totalPercent = ((hHoldings[i].UnrealizedProfitPercent + hHoldings[i + 1].UnrealizedProfitPercent) / 2); if (totalPercent > TP){ Debug("Profit, Liquidating " + holdingSymbol + " at " + totalPercent); Liquidate(hSymbols[i]); Liquidate(hSymbols[i + 1]); _symbols.Remove(hSymbols[i].Underlying); } else if (totalPercent < SL){ Debug("Loss, Liquidating " + holdingSymbol + " at " + totalPercent); Liquidate(hSymbols[i]); Liquidate(hSymbols[i + 1]); _symbols.Remove(hSymbols[i].Underlying); } i++; y++; if (y == 2){ y = 0; } } } foreach (var kvp in data.OptionChains) { var chain = kvp.Value; var symbol = kvp.Key; if (_symbols.Contains(symbol.Underlying)){ return; } var atmStraddle = chain .OrderBy(x => Math.Abs(chain.Underlying.Price - x.Strike)) .ThenByDescending(x => x.Expiry) .FirstOrDefault(); if (atmStraddle != null) { _symbols.Add(symbol.Underlying); Buy(OptionStrategies.Straddle(symbol, atmStraddle.Strike, atmStraddle.Expiry), 1); Debug(string.Format("{0} straddle orders submitted", symbol.Underlying)); } } _changes = SecurityChanges.None; } private static TimeKeeper TimeKeeper { get { return new TimeKeeper(DateTime.Now, new[] { TimeZones.NewYork }); } } public override void OnSecuritiesChanged(SecurityChanges changes) { _changes = changes; if (changes.AddedSecurities.Count > 0) { Log("Securities added: " + string.Join(",", changes.AddedSecurities.Select(x => x.Symbol.Value))); } if (changes.RemovedSecurities.Count > 0) { Log("Securities removed: " + string.Join(",", changes.RemovedSecurities.Select(x => x.Symbol.Value))); } foreach (var security in changes.RemovedSecurities) { if (security.Invested) { //Liquidate(security.Symbol); //Debug("Sold back: " + security.Symbol); } } // Add option for every added security foreach (var security in changes.AddedSecurities) { if (security is Option) continue; //if (security.Symbol.Equals("SPY")) continue; //Debug("Bought: " + security.Symbol); if (security.Symbol.Value.IndexOf(' ') != 0){ var option = AddOption(security.Symbol.Value); option.SetFilter(-2, 2, TimeSpan.FromDays(30), TimeSpan.FromDays(45)); } else { var theSymbol = security.Symbol.Value.Split(' ')[0]; var option = AddOption(theSymbol); option.SetFilter(-2, 2, TimeSpan.FromDays(30), TimeSpan.FromDays(45)); } } } } }