See that and the examples below. Hopefully this helps you as a start for your own algorithm. After you have started please feel free to share it and ak questions for more help. Also note that the IV is not currently loading however you can do the other things you mentioned like Bid/Ask spread and could also add your own modeling as your forecasted price target
Take a look at this templace for some inspiration https://github.com/QuantConnect/Lean/blob/master/Algorithm.CSharp/BasicTemplateOptionTradesAlgorithm.cs
For strike selection you can do some interesting things. such as
option.SetFilter(universe => from symbol in universe
.IncludeWeeklys()
.Expiration(TimeSpan.FromDays(1), TimeSpan.FromDays(7)) // Next 7 days
where symbol.ID.OptionRight == OptionRight.Put // Put Only
&& ((symbol.ID.StrikePrice - universe.Underlying.Price) / universe.Underlying.Price) <= 0.15m // within 15% of the underlying
select symbol);
Heres another snippet I'm using to review Bid/Ask & OI information that might be helpful for you
if (lastSlice.OptionChains.TryGetValue(_optionSymbol, out chain)) // lastSlice is a private variable that I am assigning within the OnData event
{
// find the first call strike under market price expiring today
var contracts = (
from optionContract in chain
.OrderBy(x => Math.Abs(x.UnderlyingLastPrice - x.Strike)) // find nearest options
.OrderBy(x => (x.Expiry - _algorithm.Time).TotalDays)
where optionContract.Right == OptionRight.Put
//where optionContract.Expiry > Time.Date
//where optionContract.Strike < chain.Underlying.Price
select optionContract
).Take(5).OrderBy(x => x.Strike); // 5 records
foreach (OptionContract _contract in contracts)
{
Decimal pctOtm = ((_contract.Strike - _contract.UnderlyingLastPrice) / _contract.UnderlyingLastPrice);
if (pctOtm >= 1) {pctOtm = pctOtm - 1;}
Debug(String.Format("Review Option Contract. Strike {0}, ULPrice={1}, Bid={2}, Ask={3} Spread={4}, Expiry={5:d} {6} {7} DTE, {8}% OI={9}",
_contract.Strike.ToString("N2"),
_contract.UnderlyingLastPrice.ToString("N2"),
_contract.BidPrice.ToString("N2"),
_contract.AskPrice.ToString("N2"),
(_contract.AskPrice - _contract.BidPrice).ToString("N2"),
_contract.Expiry,
_contract.Expiry.DayOfWeek.ToString(),
(_contract.Expiry - _algorithm.Time).TotalDays.ToString("N0"),
(pctOtm*100).ToString("N2"),
_contract.OpenInterest
));
}
}