- ago
Hi there! I'm trying to backtest a simple long TQQQ ATM call strategy. Buy 1 contract the day after OpEx, and sell the day of OpEx. Rinse and repeat.

I tried to implement in C# code using the webinar and Cone's blog. I think it's close, but I'm having trouble implementing historical IV using Schwab data provider. I know that you can use synthetic bars as well for the daily data, but I'd like to see historical as well.

CODE:
using WealthLab.Backtest; using System; using WealthLab.Core; using WealthLab.Data; using WealthLab.Indicators; using System.Collections.Generic; using System.Windows.Media.Imaging; namespace WealthScript1 {    public class MyStrategy : UserStrategyBase    {       string _osym;       DateTime _expiry;       BarHistory _obars; // the option's BarHistory       int _hash = -1;       UniqueList<string> _syms = new UniqueList<string>();       TimeSeries _iv; // implied volatility estimate       int useSchwab;       //create indicators and other objects here, this is executed prior to the main trading loop       public override void Initialize(BarHistory bars)       {       }       //execute the strategy rules here, this is executed once for each bar in the backtest history       public override void Execute(BarHistory bars, int idx)       {          Position opt = FindOpenPositionAllSymbols(_hash);          if (opt == null)          {             // Use a synthetic contract. Cone states in webinar that synthetic can work for daily bars.             _osym = OptionSynthetic.GetOptionsSymbol(bars, OptionType.Call, bars.Close[idx], bars.DateTimes[idx], 30, useWeeklies: false, allowExpired: true);                          _hash = Math.Abs(_osym.GetHashCode());             _expiry = OptionsHelper.SymbolExpiry(_osym);             WriteToDebugLog("-------");             WriteToDebugLog("Buying on " + bars.DateTimes[idx]);             WriteToDebugLog("Should Expire on " + _expiry);             //GetHistory generates Barhistory objects based on Stock's BarHistory and Implied IV                         _obars = OptionSynthetic.GetHistory(bars, _osym, 0.50);             _syms.Add(_obars.Symbol);             // Buy 1 Call.             Transaction t2 = PlaceTrade(_obars, TransactionType.Buy, OrderType.Market, 0, _hash, "Buy 1 call");             t2.Quantity = 1;          }          else          {             // close the position at expiry             if (bars.DateTimes[idx].AddDays(1) >= _expiry)             {                ClosePosition(opt, OrderType.Market, 0, "Expired");                WriteToDebugLog("Selling on " + bars.DateTimes[idx]);             }                          }       }       public override void Cleanup(BarHistory bars)       {          // don't overload the chart with panes - plot only the last 5 contracts that were traded in Single Symbol Mode                   if (!Backtester.Strategy.SingleSymbolMode)             return;          // Indicate the trades          foreach (Position p in GetPositionsAllSymbols())          {             if (p.Bars == bars || _syms.IndexOf(p.Symbol) < _syms.Count - 5)                continue;             PlotBarHistory(p.Bars, p.Symbol);             if (!p.NSF)             {                if (p.EntryBar > 0)                   DrawTextVAlign("▲", p.EntryBar, p.Bars.Low[p.EntryBar] * 0.95, VerticalAlignment.Top, WLColor.NeonBlue, 16, 0, 0, p.Symbol, true);                if (p.ExitBar > 0)                   DrawTextVAlign("▼", p.ExitBar, p.Bars.High[p.ExitBar] * 1.05, VerticalAlignment.Bottom, WLColor.NeonFuschia, 16, 0, 0, p.Symbol, true);             }          }       }    }
0
180
Solved
3 Replies

Reply

Bookmark

Sort
Cone8
 ( 4.83% )
- ago
#1
For historic IV, use a Historic Volatility series divided by 100. Depending on the symbol you need to play with the "hvbars" to come up with a reasonable approximation to true IV.

CODE:
using WealthLab.Backtest; using System; using WealthLab.Core; using WealthLab.Data; using WealthLab.Indicators; using System.Collections.Generic; namespace WealthScript1 {    public class MyStrategy : UserStrategyBase    {       string _osym;       DateTime _expiry;       BarHistory _obars; // the option's BarHistory       int _hash = -1;       UniqueList<string> _syms = new UniqueList<string>();       TimeSeries _iv; // implied volatility estimate       int useSchwab;       TimeSeries _hv;       //create indicators and other objects here, this is executed prior to the main trading loop       public override void Initialize(BarHistory bars)       {          int hvbars = 144;          _hv = HV.Series(bars.Close, hvbars, 89) / 100.0;          PlotTimeSeries(_hv, "HV", "HV");          StartIndex = hvbars;       }       //execute the strategy rules here, this is executed once for each bar in the backtest history       public override void Execute(BarHistory bars, int idx)       {          Position opt = FindOpenPositionAllSymbols(_hash);          if (opt == null)          {             // Use a synthetic contract. Cone states in webinar that synthetic can work for daily bars.             _osym = OptionSynthetic.GetOptionsSymbol(bars, OptionType.Call, bars.Close[idx], bars.DateTimes[idx], 30, useWeeklies: false, allowExpired: true);             _hash = Math.Abs(_osym.GetHashCode());             _expiry = OptionsHelper.SymbolExpiry(_osym);             WriteToDebugLog("-------");             WriteToDebugLog("Buying on " + bars.DateTimes[idx]);             WriteToDebugLog("Should Expire on " + _expiry);             //GetHistory generates Barhistory objects based on Stock's BarHistory and Implied IV             _obars = OptionSynthetic.GetHistory(bars, _osym, _hv);             _syms.Add(_obars.Symbol);             // Buy 1 Call.             Transaction t2 = PlaceTrade(_obars, TransactionType.Buy, OrderType.Market, 0, _hash, "Buy 1 call");             t2.Quantity = 1;          }          else          {             // close the position at expiry             if (bars.DateTimes[idx].AddDays(1) >= _expiry)             {                ClosePosition(opt, OrderType.Market, 0, "Expired");                WriteToDebugLog("Selling on " + bars.DateTimes[idx]);             }          }       }       public override void Cleanup(BarHistory bars)       {          // don't overload the chart with panes - plot only the last 5 contracts that were traded in Single Symbol Mode          if (!Backtester.Strategy.SingleSymbolMode)             return;          // Indicate the trades          foreach (Position p in GetPositionsAllSymbols())          {             if (p.Bars == bars || _syms.IndexOf(p.Symbol) < _syms.Count - 5)                continue;             PlotBarHistory(p.Bars, p.Symbol);             if (!p.NSF)             {                if (p.EntryBar > 0)                   DrawTextVAlign("▲", p.EntryBar, p.Bars.Low[p.EntryBar] * 0.95, VerticalAlignment.Top, WLColor.NeonBlue, 16, 0, 0, p.Symbol, true);                if (p.ExitBar > 0)                   DrawTextVAlign("▼", p.ExitBar, p.Bars.High[p.ExitBar] * 1.05, VerticalAlignment.Bottom, WLColor.NeonFuschia, 16, 0, 0, p.Symbol, true);             }          }       }    } }
0
Best Answer
- ago
#2
Wow, thanks Cone! Greatly appreciate the help.
1
- ago
#3
****For those of you testing out, Go to Preferences -> Backtest and make sure Futures Mode Box is checked.
1

Reply

Bookmark

Sort