Skip to content

Commit

Permalink
SAVE STATE
Browse files Browse the repository at this point in the history
  • Loading branch information
jhonabreul committed Feb 24, 2025
1 parent f9d84a6 commit 14dcc37
Show file tree
Hide file tree
Showing 6 changed files with 241 additions and 61 deletions.
27 changes: 19 additions & 8 deletions Algorithm.Python/OptionIndicatorsRegressionAlgorithm.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,15 @@ def initialize(self):
self.set_cash(100000)

self.add_equity("AAPL", Resolution.MINUTE)
option = Symbol.create_option("AAPL", Market.USA, OptionStyle.AMERICAN, OptionRight.PUT, 505, datetime(2014, 6, 27))
self.add_option_contract(option, Resolution.MINUTE)
self.option = Symbol.create_option("AAPL", Market.USA, OptionStyle.AMERICAN, OptionRight.PUT, 505, datetime(2014, 6, 27))
self.add_option_contract(self.option, Resolution.MINUTE)

self.implied_volatility = self.iv(option, option_model = OptionPricingModelType.BLACK_SCHOLES)
self.delta = self.d(option, option_model = OptionPricingModelType.BINOMIAL_COX_ROSS_RUBINSTEIN, iv_model = OptionPricingModelType.BLACK_SCHOLES)
self.gamma = self.g(option, option_model = OptionPricingModelType.FORWARD_TREE, iv_model = OptionPricingModelType.BLACK_SCHOLES)
self.vega = self.v(option, option_model = OptionPricingModelType.FORWARD_TREE, iv_model = OptionPricingModelType.BLACK_SCHOLES)
self.theta = self.t(option, option_model = OptionPricingModelType.FORWARD_TREE, iv_model = OptionPricingModelType.BLACK_SCHOLES)
self.rho = self.r(option, option_model = OptionPricingModelType.FORWARD_TREE, iv_model = OptionPricingModelType.BLACK_SCHOLES)
self.implied_volatility = self.iv(self.option, option_model = OptionPricingModelType.BLACK_SCHOLES)
self.delta = self.d(self.option, option_model = OptionPricingModelType.BINOMIAL_COX_ROSS_RUBINSTEIN, iv_model = OptionPricingModelType.BLACK_SCHOLES)
self.gamma = self.g(self.option, option_model = OptionPricingModelType.FORWARD_TREE, iv_model = OptionPricingModelType.BLACK_SCHOLES)
self.vega = self.v(self.option, option_model = OptionPricingModelType.FORWARD_TREE, iv_model = OptionPricingModelType.BLACK_SCHOLES)
self.theta = self.t(self.option, option_model = OptionPricingModelType.FORWARD_TREE, iv_model = OptionPricingModelType.BLACK_SCHOLES)
self.rho = self.r(self.option, option_model = OptionPricingModelType.FORWARD_TREE, iv_model = OptionPricingModelType.BLACK_SCHOLES)

def on_end_of_algorithm(self):
if self.implied_volatility.current.value == 0 or self.delta.current.value == 0 or self.gamma.current.value == 0 \
Expand All @@ -42,3 +42,14 @@ def on_end_of_algorithm(self):
Vega: {self.vega.current.value},
Theta: {self.theta.current.value},
Rho: {self.rho.current.value}""")

mirror = Symbol.create_option(
self.option.underlying, self.option.id.market, self.option.id.option_style,
OptionRight.Call if self.option.id.option_right == OptionRight.PUT else OptionRight.PUT,
self.option.id.strike_price, self.option.id.date
)

iv = ImpliedVolatility(self.option, mirror_option=mirror, option_model = OptionPricingModelType.BLACK_SCHOLES)
history = self.indicator_history(iv, [self.option, mirror, self.option.underlying], 4320, Resolution.MINUTE)
df = history.data_frame
self.log(history.data_frame)
10 changes: 10 additions & 0 deletions Algorithm/QCAlgorithm.Indicators.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4083,6 +4083,16 @@ private IndicatorHistory IndicatorHistory<T>(IndicatorBase<T> indicator, IEnumer
// Reset the indicator
indicator.Reset();

history = history.ToList();
var dataByTime = history.SelectMany(x => x.AllData).GroupBy(x => x.EndTime).ToDictionary(x => x.Key, x => x.ToArray());
foreach (var (endTime, data) in dataByTime)
{
if (data.Any(x => x.Symbol.SecurityType.IsOption()))
{

}
}

var indicatorType = indicator.GetType();
// Create a dictionary of the indicator properties & the indicator value itself
var indicatorsDataPointPerProperty = indicatorType.GetProperties()
Expand Down
183 changes: 131 additions & 52 deletions Algorithm/QCAlgorithm.Python.cs
Original file line number Diff line number Diff line change
Expand Up @@ -649,6 +649,62 @@ public void RegisterIndicator(Symbol symbol, PyObject indicator, PyObject pyObje
RegisterIndicator(symbol, indicator, dataConsolidator, selector);
}

private IndicatorBase ConvertPythonIndicator(PyObject pyIndicator)
{
IndicatorBase convertedIndicator;
if (pyIndicator.TryConvert(out PythonIndicator pythonIndicator))
{
convertedIndicator = WrapPythonIndicator(pyIndicator, pythonIndicator);
}
else if (pyIndicator.TryConvert(out IndicatorBase<IndicatorDataPoint> dataPointIndicator))
{
convertedIndicator = dataPointIndicator;
}
else if (pyIndicator.TryConvert(out IndicatorBase<IBaseDataBar> dataBarIndicator))
{
convertedIndicator = dataBarIndicator;
}
else if (pyIndicator.TryConvert(out IndicatorBase<TradeBar> tradeBarIndicator))
{
convertedIndicator = tradeBarIndicator;
}
else if (pyIndicator.TryConvert(out IndicatorBase<IBaseData> baseDataIndicator))
{
convertedIndicator = baseDataIndicator;
}
else
{
convertedIndicator = WrapPythonIndicator(pyIndicator);
}

return convertedIndicator;
}

private dynamic ConvertPythonIndicatorSelector(IndicatorBase convertedIndicator, PyObject selector)
{
switch (convertedIndicator)
{
case PythonIndicator pythonIndicator:
return selector?.ConvertToDelegate<Func<IBaseData, IBaseData>>();

case IndicatorBase<IndicatorDataPoint> dataPointIndicator:
return selector?.ConvertToDelegate<Func<IBaseData, decimal>>();

case IndicatorBase<IBaseDataBar> baseDataBarIndicator:
return selector?.ConvertToDelegate<Func<IBaseData, IBaseDataBar>>();

case IndicatorBase<TradeBar> tradeBarIndicator:
return selector?.ConvertToDelegate<Func<IBaseData, TradeBar>>();

case IndicatorBase<IBaseData> baseDataIndicator:
return selector?.ConvertToDelegate<Func<IBaseData, IBaseData>>();

default:
// Shouldn't happen, ConvertPythonIndicator will wrap the PyObject in a PythonIndicator instance if it can't convert it
throw new ArgumentException();
}
}

/// <summary>
/// Registers the consolidator to receive automatic updates as well as configures the indicator to receive updates
/// from the consolidator.
Expand All @@ -662,38 +718,31 @@ public void RegisterIndicator(Symbol symbol, PyObject indicator, PyObject pyObje
public void RegisterIndicator(Symbol symbol, PyObject indicator, IDataConsolidator consolidator, PyObject selector = null)
{
// TODO: to be removed when https://github.com/QuantConnect/pythonnet/issues/62 is solved
IndicatorBase<IndicatorDataPoint> indicatorDataPoint;
IndicatorBase<IBaseDataBar> indicatorDataBar;
IndicatorBase<TradeBar> indicatorTradeBar;

if (indicator.TryConvert<PythonIndicator>(out var pythonIndicator))
var convertedIndicator = ConvertPythonIndicator(indicator);
//RegisterIndicator(symbol, convertedIndicator, consolidator, ConvertPythonIndicatorSelector(convertedIndicator, selector));
if (convertedIndicator is PythonIndicator pythonIndicator)
{
RegisterIndicator(symbol, WrapPythonIndicator(indicator, pythonIndicator), consolidator,
RegisterIndicator(symbol, pythonIndicator, consolidator,
selector?.ConvertToDelegate<Func<IBaseData, IBaseData>>());
}
else if (indicator.TryConvert(out indicatorDataPoint))
else if (convertedIndicator is IndicatorBase<IndicatorDataPoint> dataPointIndicator)
{
RegisterIndicator(symbol, indicatorDataPoint, consolidator,
RegisterIndicator(symbol, dataPointIndicator, consolidator,
selector?.ConvertToDelegate<Func<IBaseData, decimal>>());
}
else if (indicator.TryConvert(out indicatorDataBar))
else if (convertedIndicator is IndicatorBase<IBaseDataBar> dataBarIndicator)
{
RegisterIndicator(symbol, indicatorDataBar, consolidator,
RegisterIndicator(symbol, dataBarIndicator, consolidator,
selector?.ConvertToDelegate<Func<IBaseData, IBaseDataBar>>());
}
else if (indicator.TryConvert(out indicatorTradeBar))
else if (convertedIndicator is IndicatorBase<TradeBar> tradeBarIndicator)
{
RegisterIndicator(symbol, indicatorTradeBar, consolidator,
RegisterIndicator(symbol, tradeBarIndicator, consolidator,
selector?.ConvertToDelegate<Func<IBaseData, TradeBar>>());
}
else if (indicator.TryConvert(out IndicatorBase<IBaseData> indicatorBaseData))
{
RegisterIndicator(symbol, indicatorBaseData, consolidator,
selector?.ConvertToDelegate<Func<IBaseData, IBaseData>>());
}
else
else if (convertedIndicator is IndicatorBase<IBaseData> baseDataIndicator)
{
RegisterIndicator(symbol, WrapPythonIndicator(indicator), consolidator,
RegisterIndicator(symbol, baseDataIndicator, consolidator,
selector?.ConvertToDelegate<Func<IBaseData, IBaseData>>());
}
}
Expand Down Expand Up @@ -1597,19 +1646,29 @@ public IDataConsolidator Consolidate(Symbol symbol, Func<DateTime, CalendarInfo>
public IndicatorHistory IndicatorHistory(PyObject indicator, PyObject symbol, int period, Resolution? resolution = null, PyObject selector = null)
{
var symbols = symbol.ConvertToSymbolEnumerable();
if (indicator.TryConvert(out IndicatorBase<IndicatorDataPoint> indicatorDataPoint))
{
return IndicatorHistory(indicatorDataPoint, symbols, period, resolution, selector?.ConvertToDelegate<Func<IBaseData, decimal>>());
}
else if (indicator.TryConvert(out IndicatorBase<IBaseDataBar> indicatorBar))
{
return IndicatorHistory(indicatorBar, symbols, period, resolution, selector?.ConvertToDelegate<Func<IBaseData, IBaseDataBar>>());
}
else if (indicator.TryConvert(out IndicatorBase<TradeBar> indicatorTradeBar))
var convertedIndicator = ConvertPythonIndicator(indicator);

switch (convertedIndicator)
{
return IndicatorHistory(indicatorTradeBar, symbols, period, resolution, selector?.ConvertToDelegate<Func<IBaseData, TradeBar>>());
case PythonIndicator pythonIndicator:
return IndicatorHistory(pythonIndicator, symbols, period, resolution, selector?.ConvertToDelegate<Func<IBaseData, IBaseData>>());

case IndicatorBase<IndicatorDataPoint> dataPointIndicator:
return IndicatorHistory(dataPointIndicator, symbols, period, resolution, selector?.ConvertToDelegate<Func<IBaseData, decimal>>());

case IndicatorBase<IBaseDataBar> baseDataBarIndicator:
return IndicatorHistory(baseDataBarIndicator, symbols, period, resolution, selector?.ConvertToDelegate<Func<IBaseData, IBaseDataBar>>());

case IndicatorBase<TradeBar> tradeBarIndicator:
return IndicatorHistory(tradeBarIndicator, symbols, period, resolution, selector?.ConvertToDelegate<Func<IBaseData, TradeBar>>());

case IndicatorBase<IBaseData> baseDataIndicator:
return IndicatorHistory(baseDataIndicator, symbols, period, resolution, selector?.ConvertToDelegate<Func<IBaseData, IBaseData>>());

default:
// Shouldn't happen, ConvertPythonIndicator will wrap the PyObject in a PythonIndicator instance if it can't convert it
throw new ArgumentException($"Indicator type {indicator.GetPythonType().Name} is not supported.");
}
return IndicatorHistory(WrapPythonIndicator(indicator), symbols, period, resolution, selector?.ConvertToDelegate<Func<IBaseData, IBaseData>>());
}

/// <summary>
Expand Down Expand Up @@ -1641,19 +1700,29 @@ public IndicatorHistory IndicatorHistory(PyObject indicator, PyObject symbol, Ti
public IndicatorHistory IndicatorHistory(PyObject indicator, PyObject symbol, DateTime start, DateTime end, Resolution? resolution = null, PyObject selector = null)
{
var symbols = symbol.ConvertToSymbolEnumerable();
if (indicator.TryConvert(out IndicatorBase<IndicatorDataPoint> indicatorDataPoint))
{
return IndicatorHistory(indicatorDataPoint, symbols, start, end, resolution, selector?.ConvertToDelegate<Func<IBaseData, decimal>>());
}
else if (indicator.TryConvert(out IndicatorBase<IBaseDataBar> indicatorBar))
{
return IndicatorHistory(indicatorBar, symbols, start, end, resolution, selector?.ConvertToDelegate<Func<IBaseData, IBaseDataBar>>());
}
else if (indicator.TryConvert(out IndicatorBase<TradeBar> indicatorTradeBar))
var convertedIndicator = ConvertPythonIndicator(indicator);

switch (convertedIndicator)
{
return IndicatorHistory(indicatorTradeBar, symbols, start, end, resolution, selector?.ConvertToDelegate<Func<IBaseData, TradeBar>>());
case PythonIndicator pythonIndicator:
return IndicatorHistory(pythonIndicator, symbols, start, end, resolution, selector?.ConvertToDelegate<Func<IBaseData, IBaseData>>());

case IndicatorBase<IndicatorDataPoint> dataPointIndicator:
return IndicatorHistory(dataPointIndicator, symbols, start, end, resolution, selector?.ConvertToDelegate<Func<IBaseData, decimal>>());

case IndicatorBase<IBaseDataBar> baseDataBarIndicator:
return IndicatorHistory(baseDataBarIndicator, symbols, start, end, resolution, selector?.ConvertToDelegate<Func<IBaseData, IBaseDataBar>>());

case IndicatorBase<TradeBar> tradeBarIndicator:
return IndicatorHistory(tradeBarIndicator, symbols, start, end, resolution, selector?.ConvertToDelegate<Func<IBaseData, TradeBar>>());

case IndicatorBase<IBaseData> baseDataIndicator:
return IndicatorHistory(baseDataIndicator, symbols, start, end, resolution, selector?.ConvertToDelegate<Func<IBaseData, IBaseData>>());

default:
// Shouldn't happen, ConvertPythonIndicator will wrap the PyObject in a PythonIndicator instance if it can't convert it
throw new ArgumentException($"Indicator type {indicator.GetPythonType().Name} is not supported.");
}
return IndicatorHistory(WrapPythonIndicator(indicator), symbols, start, end, resolution, selector?.ConvertToDelegate<Func<IBaseData, IBaseData>>());
}

/// <summary>
Expand All @@ -1665,19 +1734,29 @@ public IndicatorHistory IndicatorHistory(PyObject indicator, PyObject symbol, Da
/// <returns>pandas.DataFrame containing the historical data of <paramref name="indicator"/></returns>
public IndicatorHistory IndicatorHistory(PyObject indicator, IEnumerable<Slice> history, PyObject selector = null)
{
if (indicator.TryConvert(out IndicatorBase<IndicatorDataPoint> indicatorDataPoint))
{
return IndicatorHistory(indicatorDataPoint, history, selector?.ConvertToDelegate<Func<IBaseData, decimal>>());
}
else if (indicator.TryConvert(out IndicatorBase<IBaseDataBar> indicatorBar))
{
return IndicatorHistory(indicatorBar, history, selector?.ConvertToDelegate<Func<IBaseData, IBaseDataBar>>());
}
else if (indicator.TryConvert(out IndicatorBase<TradeBar> indicatorTradeBar))
var convertedIndicator = ConvertPythonIndicator(indicator);

switch (convertedIndicator)
{
return IndicatorHistory(indicatorTradeBar, history, selector?.ConvertToDelegate<Func<IBaseData, TradeBar>>());
case PythonIndicator pythonIndicator:
return IndicatorHistory(pythonIndicator, history, selector?.ConvertToDelegate<Func<IBaseData, IBaseData>>());

case IndicatorBase<IndicatorDataPoint> dataPointIndicator:
return IndicatorHistory(dataPointIndicator, history, selector?.ConvertToDelegate<Func<IBaseData, decimal>>());

case IndicatorBase<IBaseDataBar> baseDataBarIndicator:
return IndicatorHistory(baseDataBarIndicator, history, selector?.ConvertToDelegate<Func<IBaseData, IBaseDataBar>>());

case IndicatorBase<TradeBar> tradeBarIndicator:
return IndicatorHistory(tradeBarIndicator, history, selector?.ConvertToDelegate<Func<IBaseData, TradeBar>>());

case IndicatorBase<IBaseData> baseDataIndicator:
return IndicatorHistory(baseDataIndicator, history, selector?.ConvertToDelegate<Func<IBaseData, IBaseData>>());

default:
// Shouldn't happen, ConvertPythonIndicator will wrap the PyObject in a PythonIndicator instance if it can't convert it
throw new ArgumentException($"Indicator type {indicator.GetPythonType().Name} is not supported.");
}
return IndicatorHistory(WrapPythonIndicator(indicator), history, selector?.ConvertToDelegate<Func<IBaseData, IBaseData>>());
}

/// <summary>
Expand Down
11 changes: 10 additions & 1 deletion Common/Indicators/InternalIndicatorValues.cs
Original file line number Diff line number Diff line change
Expand Up @@ -163,12 +163,21 @@ public IndicatorPropertyValues(IIndicator indicator, PropertyInfo propertyInfo)
public override IndicatorDataPoint UpdateValue()
{
var value = _propertyInfo.GetValue(Indicator);
if (value == null)
{
return null;
}

if (_currentInfo != null)
{
value = _currentInfo.GetValue(value);
}
var point = value as IndicatorDataPoint;
Values.Add(point);
if (Values.Count == 0 || point.EndTime != Values[^1].EndTime)
{
Values.Add(point);
}

return point;
}
}
Expand Down
18 changes: 18 additions & 0 deletions Common/Python/PandasConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,24 @@ public PyObject GetDataFrame<T>(IEnumerable<T> data, bool symbolOnlyIndex = fals
/// <returns><see cref="PyObject"/> containing a pandas.DataFrame</returns>
public PyObject GetIndicatorDataFrame(IEnumerable<KeyValuePair<string, List<IndicatorDataPoint>>> data)
{
var dict = data.ToDictionary();
foreach (var kvp in dict)
{
var name = kvp.Key;
var values = kvp.Value.ToArray();
var valuesWithoutDuplicates = values.DistinctBy(x => x.EndTime).ToArray();

for (var i = 1; i < values.Length; i++)
{
var prevTime = values[i - 1].EndTime;
var time = values[i].EndTime;

if (time == prevTime)
{
}
}
}

using (Py.GIL())
{
using var pyDict = new PyDict();
Expand Down
Loading

0 comments on commit 14dcc37

Please sign in to comment.