-
-
Save yellowandy/d96c0d78a8e699a2afb5c2367becda80 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Linq; | |
using QuantConnect.Data; | |
using QuantConnect.Data.Market; | |
using QuantConnect.Orders; | |
using QuantConnect.Securities; | |
using QuantConnect.Securities.Option; | |
using QuantConnect.Indicators; | |
namespace QuantConnect | |
{ | |
/* | |
* Basic Template Algorithm | |
* | |
* The underlying QCAlgorithm class has many methods which enable you to use QuantConnect. | |
* We have explained some of these here, but the full base class can be found at: | |
* https://github.com/QuantConnect/Lean/tree/master/Algorithm | |
*/ | |
public class GreenGooseAlgorithm : QCAlgorithm | |
{ | |
private const string UnderlyingTicker = "SPY"; | |
public readonly Symbol Underlying = QuantConnect.Symbol.Create(UnderlyingTicker, SecurityType.Equity, Market.USA); | |
public readonly Symbol OptionSymbol = QuantConnect.Symbol.Create(UnderlyingTicker, SecurityType.Option, Market.USA); | |
public Option option; | |
private Slice lastSlice = null; | |
private RelativeStrengthIndex rsi2; | |
private string lastOrderSymbol = null; | |
private decimal lastOrderPrice = 0; | |
public override void Initialize() | |
{ | |
// backtest parameters | |
SetStartDate(2016, 06, 01); //Set Start Date | |
SetEndDate(2016, 07, 03); //et End Date | |
// cash allocation | |
SetCash(25000); | |
AddEquity(UnderlyingTicker, Resolution.Hour); | |
option = AddOption(UnderlyingTicker); | |
option.SetFilter(universe => from symbol in universe | |
.Expiration(TimeSpan.Zero, TimeSpan.FromDays(14)) | |
select symbol); | |
rsi2 = RSI(Underlying, 2, Indicators.MovingAverageType.Simple); | |
//Setup all events | |
scheduleEvents(); | |
} | |
public void scheduleEvents() | |
{ | |
//Open | |
Schedule.On(DateRules.EveryDay(Underlying), TimeRules.BeforeMarketClose(Underlying, 10), () => | |
{ | |
Log("EveryDay.SPY 10 min before close: Fired at: " + Time); | |
openGreenGooseOrder(); | |
}); | |
//Gap open/close | |
Schedule.On(DateRules.EveryDay(Underlying), TimeRules.AfterMarketOpen(Underlying), () => | |
{ | |
Log("Checking if we should close green goose on market open: " + Time); | |
closeGreenGooseOrderForGaps(); | |
}); | |
//Regular closes | |
Schedule.On(DateRules.EveryDay(Underlying), TimeRules.At(10, 0), () => | |
{ | |
Log("Checking if we should close green goose: " + Time); | |
closeGreenGooseOrder(); | |
}); | |
Schedule.On(DateRules.EveryDay(Underlying), TimeRules.At(10, 30), () => | |
{ | |
Log("Checking if we should close green goose: " + Time); | |
closeGreenGooseOrder(); | |
}); | |
Schedule.On(DateRules.EveryDay(Underlying), TimeRules.At(11, 0), () => | |
{ | |
Log("Checking if we should close green goose: " + Time); | |
closeGreenGooseOrder(); | |
}); | |
Schedule.On(DateRules.EveryDay(Underlying), TimeRules.At(11, 30), () => | |
{ | |
Log("Checking if we should close green goose: " + Time); | |
closeGreenGooseOrder(); | |
}); | |
Schedule.On(DateRules.EveryDay(Underlying), TimeRules.At(12, 00), () => | |
{ | |
Log("Checking if we should close green goose: " + Time); | |
closeGreenGooseOrder(); | |
}); | |
Schedule.On(DateRules.EveryDay(Underlying), TimeRules.At(12, 30), () => | |
{ | |
Log("Checking if we should close green goose: " + Time); | |
closeGreenGooseOrder(); | |
}); | |
Schedule.On(DateRules.EveryDay(Underlying), TimeRules.At(13, 00), () => | |
{ | |
Log("Checking if we should close green goose: " + Time); | |
closeGreenGooseOrder(); | |
}); | |
} | |
//public void getAtmOptionContracts() | |
//{ | |
// option | |
// var atmContract = chain | |
// .OrderByDescending(x => x.Expiry) | |
// .ThenBy(x => Math.Abs(chain.Underlying.Price - x.Strike)) | |
// .FirstOrDefault(); | |
//} | |
public void closeGreenGooseOrderForGaps() | |
{ | |
} | |
public void closeGreenGooseOrder() | |
{ | |
Log("Calling close green goose....."); | |
if (Securities[UnderlyingTicker].Holdings.Quantity > 0) | |
{ | |
Log("Closing: found open orders to close......"); | |
} | |
} | |
public decimal calculatePercentageDifference(decimal startPrice, decimal endPrice) | |
{ | |
Log("Staring to calculate percentDifference: " + startPrice + " " + endPrice); | |
return (endPrice - startPrice) / startPrice; | |
} | |
public void buyOptionsATM(Slice slice, string optionType) | |
{ | |
Log("Staring to buy option with slice: " + slice); | |
OptionChain chain; | |
if (slice.OptionChains.TryGetValue(OptionSymbol, out chain)) | |
{ | |
var optionRight = OptionRight.Put; | |
if(optionType == "Call" || optionType == "call") { | |
Log("Selected call right"); | |
optionRight = OptionRight.Call; | |
} | |
else if(optionType == "Put" || optionType == "put") { | |
Log("Selected put right"); | |
optionRight = OptionRight.Put; | |
} | |
var contract = ( | |
from optionContract in chain.OrderByDescending(x => x.Expiry) | |
.ThenBy(x => Math.Abs(chain.Underlying.Price - x.Strike)) | |
where optionContract.Right == optionRight | |
select optionContract | |
).FirstOrDefault(); | |
if (contract != null) | |
{ | |
Log("Placing market order for " + contract.Symbol); | |
//MarketOrder(contract.Symbol, 100); | |
SetHoldings(contract.Symbol, .15); | |
} | |
else | |
{ | |
Log("------> Unable to find contract when trying to open norder"); | |
Log("----------->" + optionRight); | |
Log("----------->" + slice); | |
} | |
} | |
else | |
{ | |
Log("------> Unable to find option chain when trying to open order 2"); | |
} | |
} | |
public void openGreenGooseOrder() | |
{ | |
Log("Opening green gose order"); | |
if (!rsi2.IsReady) return; | |
if (rsi2 <= 15) | |
{ | |
Log("RSI Less than 15 buying call options"); | |
buyOptionsATM(lastSlice, "Call"); | |
} | |
else if (rsi2 >= 85) | |
{ | |
Log("RSI greater than 85 buying options"); | |
buyOptionsATM(lastSlice, "Put"); | |
} | |
else { | |
Log("Not opening trade, RSI not a good value: " + rsi2); | |
} | |
} | |
/// <summary> | |
/// Event - v3.0 DATA EVENT HANDLER: (Pattern) Basic template for user to override for receiving all subscription data in a single event | |
/// </summary> | |
/// <param name="slice">The current slice of data keyed by symbol string</param> | |
public override void OnData(Slice slice) | |
{ | |
lastSlice = slice; | |
// Log("Got on data slice at time " + slice.Time); | |
if (IsWarmingUp) { return; } | |
// if (!rsi2.IsReady) return; | |
OptionChain chain; | |
if(lastOrderSymbol == null) { | |
//Log("No last open orders, nothing to do"); | |
return; | |
} | |
if (slice.OptionChains.TryGetValue(OptionSymbol, out chain)) | |
{ | |
// find the second call strike under market price expiring today | |
var contract = ( | |
from optionContract in chain.OrderByDescending(x => x.Strike) | |
where optionContract.Symbol == lastOrderSymbol | |
select optionContract | |
).FirstOrDefault(); | |
if(contract != null) { | |
Log("Last price is: " + contract.LastPrice); | |
var percentDifference = calculatePercentageDifference(lastOrderPrice, contract.LastPrice); | |
Log("Percentage difference is: " + percentDifference); | |
if(percentDifference >= .20M || percentDifference <= -.10m) { | |
Liquidate(lastOrderSymbol); | |
lastOrderSymbol = null; | |
} | |
} | |
Log("All done...."); | |
} | |
//return; | |
// // slice has lots of useful information | |
// TradeBars bars = data.Bars; | |
//Splits splits = data.Splits; | |
//Dividends dividends = data.Dividends; | |
////Get just this bar. | |
//TradeBar bar; | |
//if (bars.ContainsKey("SPY")) bar = bars["SPY"]; | |
//if (!Portfolio.HoldStock) | |
//{ | |
// // place an order, positive is long, negative is short. | |
// // int quantity = Portfolio.Cash / bar.Close; | |
// // Order("SPY", quantity); | |
// // or request a fixed fraction of a specific asset. | |
// // +1 = 100% long. -2 = short all capital with 2x leverage. | |
// SetHoldings("SPY", 1); | |
// // debug message to your console. Time is the algorithm time. | |
// // send longer messages to a file - these are capped to 10kb | |
// Debug("Purchased SPY on " + Time.ToShortDateString()); | |
// //Log("This is a longer message send to log."); | |
//} | |
} | |
public override void OnOrderEvent(OrderEvent fill) | |
{ | |
lastOrderSymbol = fill.Symbol; | |
lastOrderPrice = fill.FillPrice; | |
string message = String.Format("**************************** Order status:{0} quantity:{1} x symbol:{2} fill price:{3} commission={4} OrderId={5}", | |
fill.Status.ToString(), | |
fill.FillQuantity, | |
fill.Symbol, | |
fill.FillPrice, | |
fill.OrderFee, | |
fill.OrderId); | |
Log(message); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment