I am trying to convert the strategy below to QC in order to be able to test and have the ability to test with Interactive Brokers.
Assistance is greatly appreciated.
/* Modified as described in post #33*/
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using WealthLab;
using WealthLab.Indicators;
using System.Globalization;
namespace WealthLab.Strategies
{
public class OptionATMv2 : WealthScript
{
Dictionary<string, Bars> _contracts;
StrategyParameter _plot;
StrategyParameter _minDays;
StrategyParameter _round;
StrategyParameter _fast;
StrategyParameter _slow;
public OptionATMv2()
{
_plot = CreateParameter("Plot Options=1", 1, 0, 1, 1);
_minDays = CreateParameter("Days out (min)", 1, 0, 21, 1);
_round = CreateParameter("Round down", 1, 0.5, 5, 0.5);
_fast = CreateParameter("EMA fast", 10, 2, 20, 2);
_slow = CreateParameter("EMA slow", 30, 20, 50, 5);
}
private DateTime OptionExpiryDateForMonth(DateTime tempDate)
{
tempDate = new DateTime(tempDate.Year, tempDate.Month, 1);
while (tempDate.DayOfWeek != DayOfWeek.Friday) // find first friday
tempDate = tempDate.AddDays(1);
return tempDate.AddDays(14); // add two weeks
}
double FloorIt(double price, double interval)
{
double f = 1d / interval;
double r = price * f;
r = Math.Floor(r);
r /= f;
return r;
}
string GetOptionSymbol(string underlying, DateTime expiry, double strike, bool call = true)
{
string putcall = call == true ? "C" : "P";
return String.Format("-{0}{1}{2}{3}", underlying, expiry.ToString("yyMMdd"), putcall, strike);
}
string GetATMOptionSymbol(int bar, bool call = true)
{
double strike = FloorIt(Close[bar], _round.Value);
string osym = GetOptionSymbol(Bars.Symbol, GetNextExpiry(bar), strike, call);
//PrintDebug(bar + "\t" + Date[bar].ToString("yyyyMMdd") + "\t" + osym);
return osym;
}
// Find the expiry at least n calendar days out from the last bar
DateTime GetNextExpiry(int bar)
{
DateTime nextExpiry = NextOptionExpiryDate(bar);
int tradingdays = this.TradingDaysBetweenDates(Date[bar].Date, nextExpiry);
if (tradingdays < _minDays.ValueInt)
nextExpiry = OptionExpiryDateForMonth(nextExpiry.AddMonths(1));
return nextExpiry;
}
Bars GetOptionData(int bar, bool isCall = true)
{
DateTime nextExpiry = GetNextExpiry(bar);
double strike = FloorIt(Close[bar], _round.Value);
Bars obars = CreateSyntheticOption(nextExpiry.AddMonths(-2), nextExpiry, strike, isCall);
return obars;
}
// return a date 1 day prior to expiry
DateTime OptionExDate(string osymbol)
{
// e.g. !SPY_216.00_161216_CALL
string[] s = osymbol.Split(new char[] {'_'});
DateTime exdate = DateTime.ParseExact(s[2], "yyMMdd", new CultureInfo("en-US"));
return exdate.Date.AddDays(-1);
}
protected override void Execute()
{
ClearDebug();
// Dictionary to hold on-demand contracts
_contracts = new Dictionary <string, Bars>();
// Let's put the most recent data in the dictionary
Bars obars = GetOptionData(Bars.Count - 1);
_contracts.Add(obars.Symbol, obars);
// Create and plot the EMAs of the underlying
DataSeries ema10 = EMA.Series(Close, _fast.ValueInt, EMACalculation.Modern);
DataSeries ema30 = EMA.Series(Close, _slow.ValueInt, EMACalculation.Modern);
PlotSeries(PricePane, ema10, Color.Blue, LineStyle.Solid, 1);
PlotSeries(PricePane, ema30, Color.Red, LineStyle.Solid, 1);
HideVolume();
for(int bar = 20; bar < Bars.Count; bar++)
{
if (IsLastPositionActive)
{
Position p = LastPosition;
if (Bars.IsLastBarOfDay(bar))
ExitAtClose(bar, p);
else if (CrossUnder(bar, ema10, ema30)
|| Date[bar] >= OptionExDate(p.Symbol))
{
ExitAtMarket(bar + 1, p);
SetPaneBackgroundColor(PricePane, bar, Color.FromArgb(40, Color.Red));
}
}
else if (CrossOver(bar, ema10, ema30))
{
/* Buy the ATM call */
obars = GetOptionData(bar);
if (!_contracts.ContainsKey(obars.Symbol)) _contracts.Add(obars.Symbol, obars);
SetContext(obars);
BuyAtMarket(bar + 1);
SetBackgroundColor(bar, Color.FromArgb(40, Color.Green));
RestoreContext();
}
}
if (_plot.ValueInt == 1)
{
// Done trading, let's plot the option contracts and trades
foreach (KeyValuePair<string, Bars> kvp in _contracts)
{
//PrintDebug(kvp.Key);
Bars optBars = kvp.Value;
if (optBars != null)
{
ChartPane optPane = CreatePane(20, true, true);
PlotSymbol(optPane, optBars, Color.Green, Color.Red);
this.PlotSymbolTrades(optBars, optPane);
}
}
}
}
}
}
Alexandre Catarino
We cannot convert this strategy to QC since it is trading options and we do not support this security type yet.
When options support is released, there will be documention and examples that will help us to implement this strategy. Stay tuned!
Ted Penner
Thanks Alex. Do you know of any active other community of C# coders that might currently be able to help with this?
Alexandre Catarino
Sorry, Ted, I do not.
However, since this is a WeathLab script, you could seek for help in a WealthLab forum, right?
Ted Penner
Yeah, I can, but discussions about moving it to Interactive Brokers (IB) fall on deaf ears. The whole purpose of moving to C# was to be able to collaborate with anyone anywhere, so now I am just looking for a good resource. The challenge now, like you mentioned, is that most brokers don't support C# code and options. I'm not even sure if IB does.
Fernando Arámburu
Ted, hope this help in some way, but we work for a customer and in their project we do option trading with IB in C#. Obviously that was not easy, but doable. We have our software trading options automatically. Sad to say that I can't share the code due to multiple NDAs but it is possible.
Ted Penner
The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.
To unlock posting to the community forums please complete at least 30% of Boot Camp.
You can continue your Boot Camp training progress from the terminal. We hope to see you in the community soon!