Overall Statistics |
Total Trades 98 Average Win 0.71% Average Loss -0.64% Compounding Annual Return -22.977% Drawdown 9.200% Expectancy -0.297 Net Profit -8.550% Sharpe Ratio -4.913 Loss Rate 67% Win Rate 33% Profit-Loss Ratio 1.11 Alpha -0.202 Beta -0.045 Annual Standard Deviation 0.043 Annual Variance 0.002 Information Ratio -3.64 Tracking Error 0.117 Treynor Ratio 4.684 Total Fees $24.50 |
using QuantConnect.Securities.Option; using System.Net; namespace QuantConnect { public class StraddleFundamentalAlgorithm : QCAlgorithm { public class ListTuple: List<Tuple<DateTime, string>> { public DateTime date {get;set;} public string ticker {get; set;} public ListTuple(DateTime _date, string _ticker) { date = _date; ticker = _ticker; } } public List<ListTuple> ReadEarningData(){ WebClient webClient = new WebClient(); string theText = webClient.DownloadString("http://tradeitforweed.ca/earnings_sql3.csv"); string[] lines = theText.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.None); List<ListTuple> splitted = new List<ListTuple>(); foreach (var line in lines){ if(line.Split(',')[0].Length != 0){ ListTuple example = new ListTuple(DateTime.ParseExact(line.Split(',')[0], "M/d/yyyy", CultureInfo.InvariantCulture), line.Split(',')[1]); splitted.Add(example); } } return splitted; } 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(2012, 01, 01); SetEndDate(2012, 5, 5); 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) { List<ListTuple> earnings = ReadEarningData(); List<string> list = new List<string>(); Schedule.On(DateRules.EveryDay(), TimeRules.At(9, 0), () => { // Check the next earnings. var nextEarnings = earnings.Where(x => x.date == Time.Date.AddDays(-14)).ToArray(); foreach (var nextEarning in nextEarnings) { Log(nextEarning.ticker); // Just an example, implement your logic here. list.Add(nextEarning.ticker); } } ); IEnumerable<Symbol> second = list.Cast<Symbol>(); return second; } 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)); } } } } }