Skip to content

Commit

Permalink
Handle Greeks unwrapping by PandasData
Browse files Browse the repository at this point in the history
  • Loading branch information
jhonabreul committed Sep 26, 2024
1 parent 5ef2302 commit 5d0e18d
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 46 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ private Symbol GetContract(OptionChains chains, Symbol underlying, TimeSpan expi
// Get contracts expiring within a given span, with an implied volatility greater than 0.5 and a delta less than 0.5
.Where(contractData => contractData.ID.Date - Time <= expirySpan &&
contractData.ImpliedVolatility > 0.5m &&
contractData.Delta < 0.5m)
contractData.Greeks.Delta < 0.5m)
// Get the contract with the latest expiration date
.OrderByDescending(x => x.ID.Date)
.First();
Expand Down
25 changes: 0 additions & 25 deletions Common/Data/Market/OptionContract.cs
Original file line number Diff line number Diff line change
Expand Up @@ -87,31 +87,6 @@ public Symbol Symbol
/// </summary>
public Greeks Greeks => _optionData.Greeks;

/// <summary>
/// Gets the delta. Pass-through for <see cref="Greeks.Delta"/>
/// </summary>
public decimal Delta => Greeks.Delta;

/// <summary>
/// Gets the gamma. Pass-through for <see cref="Greeks.Gamma"/>
/// </summary>
public decimal Gamma => Greeks.Gamma;

/// <summary>
/// Gets the vega. Pass-through for <see cref="Greeks.Vega"/>
/// </summary>
public decimal Vega => Greeks.Vega;

/// <summary>
/// Gets the theta. Pass-through for <see cref="Greeks.Theta"/>
/// </summary>
public decimal Theta => Greeks.Theta;

/// <summary>
/// Gets the rho. Pass-through for <see cref="Greeks.Rho"/>
/// </summary>
public decimal Rho => Greeks.Rho;

/// <summary>
/// Gets the local date time this contract's data was last updated
/// </summary>
Expand Down
108 changes: 88 additions & 20 deletions Common/Python/PandasData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,22 @@ public class PandasData
private static readonly string[] _optionContractExcludedMembers = new[]
{
nameof(OptionContract.ID),
nameof(OptionContract.Greeks)
};

private static readonly string[] _greeksMemberNames = new[]
{
nameof(Greeks.Delta),
nameof(Greeks.Gamma),
nameof(Greeks.Vega),
nameof(Greeks.Theta),
nameof(Greeks.Rho),
};

private static readonly MemberInfo[] _greeksMembers = typeof(Greeks)
.GetMembers(BindingFlags.Instance | BindingFlags.Public)
.Where(x => (x.MemberType == MemberTypes.Field || x.MemberType == MemberTypes.Property) && _greeksMemberNames.Contains(x.Name))
.ToArray();

// we keep these so we don't need to ask for them each time
private static PyString _empty;
private static PyObject _pandas;
Expand Down Expand Up @@ -138,6 +151,7 @@ public PandasData(object data)
foreach (var item in enumerable)
{
data = item;
baseData = data as IBaseData;
break;
}
}
Expand Down Expand Up @@ -206,6 +220,26 @@ public PandasData(object data)
_members = members.Where(x => keys.Contains(x.Name.ToLowerInvariant())).ToList();
_membersByType.TryAdd(type, _members);
}

// Make sure to add the greeks member names to the series so they can be added to the data frame
if (_members.Any(member =>
{
var memberType = member switch
{
PropertyInfo property => property.PropertyType,
FieldInfo field => field.FieldType,
// Should not happen
_ => throw new InvalidOperationException($"Unexpected member type: {member.MemberType}")
};

return memberType.IsAssignableTo(typeof(Greeks));
}))
{
foreach (var greek in _greeksMemberNames)
{
keys.Add(greek.ToLowerInvariant());
}
}
}

var customColumns = new HashSet<string>(columns) { "value" };
Expand All @@ -231,25 +265,31 @@ public void Add(object baseData)

foreach (var member in _members)
{
// TODO field/property.GetValue is expensive
var key = member.Name.ToLowerInvariant();
var propertyMember = member as PropertyInfo;
if (propertyMember != null)
var memberType = member switch
{
var propertyValue = propertyMember.GetValue(baseData);
if (_isFundamentalType && propertyMember.PropertyType.IsAssignableTo(typeof(FundamentalTimeDependentProperty)))
{
propertyValue = ((FundamentalTimeDependentProperty)propertyValue).Clone(new FixedTimeProvider(endTime));
}
AddToSeries(key, endTime, propertyValue);
continue;
PropertyInfo property => property.PropertyType,
FieldInfo field => field.FieldType,
// Should not happen
_ => throw new InvalidOperationException($"Unexpected member type: {member.MemberType}")
};

if (!memberType.IsAssignableTo(typeof(Greeks)))
{
AddMemberToSeries(baseData, endTime, member);
}
else
{
var fieldMember = member as FieldInfo;
if (fieldMember != null)
var greeks = member switch
{
PropertyInfo property => property.GetValue(baseData),
FieldInfo field => field.GetValue(baseData),
// Should not happen
_ => throw new InvalidOperationException($"Unexpected member type: {member.MemberType}")
};

foreach (var greekMember in _greeksMembers)
{
AddToSeries(key, endTime, fieldMember.GetValue(baseData));
AddMemberToSeries(greeks, endTime, greekMember);
}
}
}
Expand All @@ -267,13 +307,41 @@ public void Add(object baseData)
AddToSeries(kvp.Key, endTime, kvp.Value);
}
}
else
else if (baseData is Tick tick)
{
AddTick(tick);
}
else if (baseData is TradeBar tradeBar)
{
Add(tradeBar, null);
}
else if (baseData is QuoteBar quoteBar)
{
AddTick(baseData as Tick);
Add(null, quoteBar);
}
}

var tradeBar = baseData as TradeBar;
var quoteBar = baseData as QuoteBar;
Add(tradeBar, quoteBar);
private void AddMemberToSeries(object baseData, DateTime endTime, MemberInfo member)
{
// TODO field/property.GetValue is expensive
var key = member.Name.ToLowerInvariant();
var propertyMember = member as PropertyInfo;
if (propertyMember != null)
{
var propertyValue = propertyMember.GetValue(baseData);
if (_isFundamentalType && propertyMember.PropertyType.IsAssignableTo(typeof(FundamentalTimeDependentProperty)))
{
propertyValue = ((FundamentalTimeDependentProperty)propertyValue).Clone(new FixedTimeProvider(endTime));
}
AddToSeries(key, endTime, propertyValue);
}
else
{
var fieldMember = member as FieldInfo;
if (fieldMember != null)
{
AddToSeries(key, endTime, fieldMember.GetValue(baseData));
}
}
}

Expand Down

0 comments on commit 5d0e18d

Please sign in to comment.