| Overall Statistics |
|
Total Trades 26 Average Win 0.40% Average Loss -0.48% Compounding Annual Return -4.343% Drawdown 1.900% Expectancy -0.213 Net Profit -1.493% Sharpe Ratio -1.55 Loss Rate 57% Win Rate 43% Profit-Loss Ratio 0.84 Alpha 0.03 Beta -3.86 Annual Standard Deviation 0.026 Annual Variance 0.001 Information Ratio -2.244 Tracking Error 0.026 Treynor Ratio 0.01 Total Fees $5.00 |
using System.Drawing;
using System.Threading;
using System.Threading.Tasks;
// Bull Put Spread - sell 1 Put below the underlying price (ATM) to get premium
// and buy 1 Put lower (OTM) to protect ourselves from market move against us
namespace QuantConnect
{
public partial class BullPutSpread : QCAlgorithm
{
string iSymbol = "MSFT";
DateTime iTime;
public override void Initialize()
{
SetCash(10000);
SetStartDate(2018, 1, 1);
SetEndDate(DateTime.Now.Date);
SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage);
AddEquity(iSymbol, Resolution.Minute);
}
public void OnData(TradeBars data)
{
if (IsMarketOpen(iSymbol) == false)
{
return;
}
if (IsNewBar(TimeSpan.FromHours(1)) == false)
{
return;
}
var price = Securities[iSymbol].Price;
// If options were exercised and we were assigned to buy shares, sell them immediately
if (Portfolio[iSymbol].Invested)
{
MarketOrder(iSymbol, -100);
}
if (Portfolio.Invested == false)
{
var contracts = OptionChainProvider.GetOptionContractList(iSymbol, Time);
// Choose all contracts within a month and strike price $1 to $5 from current underlying price
var atmPuts =
from c in contracts
where c.ID.OptionRight == OptionRight.Put
where price - c.ID.StrikePrice < 3 && price - c.ID.StrikePrice > 1
where (c.ID.Date - Time).TotalDays < 35 && (c.ID.Date - Time).TotalDays > 0
select c;
// Choose all contracts within a month and strike price $1 to $5 from current underlying price
var otmPuts =
from c in contracts
where c.ID.OptionRight == OptionRight.Put
where price - c.ID.StrikePrice < 7 && price - c.ID.StrikePrice > 5
where (c.ID.Date - Time).TotalDays < 35 && (c.ID.Date - Time).TotalDays > 0
select c;
// Take ATM options with the MIN expiration date and MAX distance from underlying price
var contractAtmPut = atmPuts
.OrderBy(o => o.ID.Date)
.ThenBy(o => price - o.ID.StrikePrice)
.FirstOrDefault();
// Take OTM options with the MIN expiration date and MAX distance from underlying price
var contractOtmPut = otmPuts
.OrderBy(o => o.ID.Date)
.ThenBy(o => price - o.ID.StrikePrice)
.FirstOrDefault();
// If we found such options - open trade
if (contractAtmPut != null &&
contractOtmPut != null)
{
AddOptionContract(contractAtmPut, Resolution.Minute);
AddOptionContract(contractOtmPut, Resolution.Minute);
MarketOrder(contractAtmPut, -1);
MarketOrder(contractOtmPut, 1);
}
}
}
public bool IsNewBar(TimeSpan interval, int points = 1)
{
var date = Securities[iSymbol].LocalTime;
if ((date - iTime).TotalSeconds > interval.TotalSeconds * points)
{
iTime = new DateTime(date.Ticks - date.Ticks % interval.Ticks, date.Kind);
return true;
}
return false;
}
}
}