| Overall Statistics |
|
Total Trades 4 Average Win 0% Average Loss 0% Compounding Annual Return 0% Drawdown 0% Expectancy 0 Net Profit 0% Sharpe Ratio 0 Sortino Ratio 0 Probabilistic Sharpe Ratio 0% Loss Rate 0% Win Rate 0% Profit-Loss Ratio 0 Alpha 0 Beta 0 Annual Standard Deviation 0 Annual Variance 0 Information Ratio 0 Tracking Error 0 Treynor Ratio 0 Total Fees $0.00 Estimated Strategy Capacity $0 Lowest Capacity Asset SPY 32F2NS2R3N36U|SPY R735QTJ8XC9X Portfolio Turnover 0.05% |
#region imports
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Globalization;
using System.Drawing;
using QuantConnect;
using QuantConnect.Algorithm.Framework;
using QuantConnect.Algorithm.Framework.Selection;
using QuantConnect.Algorithm.Framework.Alphas;
using QuantConnect.Algorithm.Framework.Portfolio;
using QuantConnect.Algorithm.Framework.Execution;
using QuantConnect.Algorithm.Framework.Risk;
using QuantConnect.Parameters;
using QuantConnect.Benchmarks;
using QuantConnect.Brokerages;
using QuantConnect.Util;
using QuantConnect.Interfaces;
using QuantConnect.Algorithm;
using QuantConnect.Indicators;
using QuantConnect.Data;
using QuantConnect.Data.Consolidators;
using QuantConnect.Data.Custom;
using QuantConnect.DataSource;
using QuantConnect.Data.Fundamental;
using QuantConnect.Data.Market;
using QuantConnect.Data.UniverseSelection;
using QuantConnect.Notifications;
using QuantConnect.Orders;
using QuantConnect.Orders.Fees;
using QuantConnect.Orders.Fills;
using QuantConnect.Orders.Slippage;
using QuantConnect.Scheduling;
using QuantConnect.Securities;
using QuantConnect.Securities.Equity;
using QuantConnect.Securities.Future;
using QuantConnect.Securities.Option;
using QuantConnect.Securities.Forex;
using QuantConnect.Securities.Crypto;
using QuantConnect.Securities.Interfaces;
using QuantConnect.Storage;
using QuantConnect.Data.Custom.AlphaStreams;
using QCAlgorithmFramework = QuantConnect.Algorithm.QCAlgorithm;
using QCAlgorithmFrameworkBridge = QuantConnect.Algorithm.QCAlgorithm;
#endregion
namespace QuantConnect.Algorithm.CSharp
{
public class DirectionalIronFly : QCAlgorithm
{
private String _ticker = "SPY";
private Symbol _symbol;
public override void Initialize()
{
SetStartDate(2024, 2, 8);
//SetEndDate(2024,1,31);
SetCash(GetParameter("InitialCashAmount", 100000));
SetWarmUp(TimeSpan.FromDays(30));
Portfolio.MarginCallModel = MarginCallModel.Null;
var seeder = new FuncSecuritySeeder(GetLastKnownPrices);
SetSecurityInitializer(security => seeder.SeedSecurity(security));
_symbol = AddEquity(_ticker, dataNormalizationMode: DataNormalizationMode.Raw, resolution: Resolution.Minute).Symbol;
}
/// OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
/// Slice object keyed by symbol containing the stock data
public override void OnData(Slice slice)
{
if (IsWarmingUp) return;
if (!IsMarketOpen(_symbol) || !TradingCalendar.GetTradingDay(Time).BusinessDay)
{
return;
}
if ((Time.Hour <= 9 && Time.Minute < 40)) return;
IEnumerable<Symbol> optionSymbols = OptionChainProvider.GetOptionContractList(_ticker, Time);
if ( !(Time.Hour == 12 && Time.Minute == 45)) return;
DateTime expiry = DateTime.MinValue;
switch (Time.DayOfWeek )
{
case DayOfWeek.Monday: case DayOfWeek.Tuesday:
expiry = Time.AddDays(3);
break;
case DayOfWeek.Wednesday: case DayOfWeek.Thursday: case DayOfWeek.Friday:
expiry = Time.AddDays(5);
break;
}
var expiryTradingDay = TradingCalendar.GetTradingDay(expiry);
if (!expiryTradingDay.BusinessDay)
{
Log(expiry.ToString() + " is not a trading day, so not opening a position");
return;
}
if (expiry > Time && expiry <= DateTime.Now)
{
decimal atmStrike = Math.Round(Securities[_symbol].Price);
decimal shortCallStrike = atmStrike + 2;
decimal shortPutStrike = atmStrike + 2;
decimal longCallStrike = atmStrike + 10;
decimal longPutStrike = atmStrike - 10;
Symbol offsetCallSymbol = null;
offsetCallSymbol = optionSymbols.Where(x => x.ID.Date.Date == expiry.Date && x.ID.OptionRight == OptionRight.Call && x.ID.StrikePrice == shortCallStrike)
.First();
Symbol offsetPutSymbol = optionSymbols.Where(x => x.ID.Date.Date == expiry.Date && x.ID.OptionRight == OptionRight.Put && x.ID.StrikePrice == shortPutStrike)
.First();
Symbol longCallSymbol = null;
while (longCallSymbol == null)
{
try
{
longCallSymbol = optionSymbols.Where(x => x.ID.Date.Date == expiry.Date && x.ID.OptionRight == OptionRight.Call && x.ID.StrikePrice == (longCallStrike))
.First();
}
catch
{
longCallStrike++;
}
}
Symbol longPutSymbol = optionSymbols.Where(x => x.ID.Date.Date == expiry.Date && x.ID.OptionRight == OptionRight.Put && x.ID.StrikePrice <= (longPutStrike))
.OrderByDescending(x => x.ID.StrikePrice)
.First();
Option longPutOption = AddOptionContract(longPutSymbol, Resolution.Minute);
Option offsetPutOption = AddOptionContract(offsetPutSymbol, Resolution.Minute);
Option offsetCallOption = AddOptionContract(offsetCallSymbol, Resolution.Minute);
Option longCallOption = AddOptionContract(longCallSymbol, Resolution.Minute);
Securities[longPutOption.Symbol].SetFeeModel(new ConstantFeeModel(0));
Securities[longCallOption.Symbol].SetFeeModel(new ConstantFeeModel(0));
Securities[offsetPutOption.Symbol].SetFeeModel(new ConstantFeeModel(0));
Securities[offsetCallOption.Symbol].SetFeeModel(new ConstantFeeModel(0));
longPutOption.SetOptionAssignmentModel(new NullOptionAssignmentModel());
longCallOption.SetOptionAssignmentModel(new NullOptionAssignmentModel());
offsetPutOption.SetOptionAssignmentModel(new NullOptionAssignmentModel());
offsetCallOption.SetOptionAssignmentModel(new NullOptionAssignmentModel());
List<Leg> orderLegs = new List<Leg>()
{
Leg.Create(longPutSymbol, 1),
Leg.Create(offsetPutSymbol, -1),
Leg.Create(offsetCallSymbol, -1),
Leg.Create(longCallSymbol, 1)
};
List<OrderTicket> newIronFlyOrderTickets = ComboMarketOrder(orderLegs, 1);
if(newIronFlyOrderTickets.Count < 4)
{
Log("ComboMarketOrder only returned " + newIronFlyOrderTickets.Count + " Order Tickets, so an order was not created successfully "
+ longPutSymbol.Value + " "
+ offsetPutSymbol.Value + " "
+ offsetCallSymbol.Value + " "
+ longCallSymbol.Value + " ");
return;
}
Log("New Iron Fly Order for "
+ expiry.ToShortDateString()
+ " Price " + newIronFlyOrderTickets.Sum(x => x.AverageFillPrice * x.QuantityFilled)
+ " Long Put Strike " + longPutSymbol.ID.StrikePrice
+ " ATM Put Strike " + offsetPutSymbol.ID.StrikePrice
+ " ATM Call Strike " + offsetCallSymbol.ID.StrikePrice
+ " Long Call Strike " + longCallSymbol.ID.StrikePrice);
}
}
}
}