Closed erv4gen closed 4 years ago
Hi Vladimir,
Thanks for you suggestion! I've actually been thinking about the same problem myself and have decided to implement it as a core feature in the upcoming v2 update that I am working on.
I plan on making v2 event driven, that is, events can be generated from stocks, sentiment and other external data.
class SampleStrategy(op.Strategy):
"""
This is a sample strategy to simulate a portolio of SPX call spreads
hedged by VXX calls.
"""
def on_init(self):
"""
Define any initialization logic here
"""
self.set_cash(10000.0)
self.set_brokerage(op.Brokerage.THINKORSWIM)
self.start_date = datetime(2018, 1, 1)
self.end_date = datetime(2018, 12, 31)
self.calendar.every(op.DayOfWeek.Thursday, self.open_trade)
def open_trade(self):
"""
Rules to open a new trade
"""
self.buy(
(
self.get_instrument("SPX")
.verticals.call_spread()
.select_by(scale=False)
.days_to_expiration(min_days=40, max_days=47)
.abs_deltas(leg1=0.30, leg2=0.50)
)
)
self.buy(
(
self.get_instrument("VXX")
.singles.calls()
.select_by(scale=False)
.days_to_expiration(min_days=40, max_days=47)
.abs_deltas(leg1=0.20)
)
)
def on_next(self, event):
"""
Define your trading logic here, each new event
will be attached to the event variable.
Arguments:
event: Dict object containing metadata for the event
Bar event example:
{
type: Event.BAR,
data: {
"SPX": [...],
"VXX": [...]
}
}
"""
if event.type == Event.BAR:
# do something related to price action here
elif event.type == Event.SENTIMENT:
# do something related to sentiment signals here
elif event.type == Event.SIGNAL:
# do something related to indicator signals here
def run_strategy():
# create our inport dataframes
spx = pd.read_csv("spx.csv")
vxx = pd.read_csv("vxx.csv")
earnings = pd.read_csv("earnings_signals.csv")
macd_signals = pd.read_csv("macd_signals.csv")
# create a new backtest instance
backtest = op.Backtest()
# load the data from our dataframes
backtest.load_data(SPX=spx, VXX=vxx)
backtest.load_sentiment(earnings=earnings)
backtest.load_signals(macd=macd_signals)
backtest.add_strategy(SampleStrategy)
backtest.run().plot()
if __name__ == "__main__":
run_strategy()
Feel free to check out the WIP strategy-refactor branch, any feedback/suggestions welcomed!
Yes, that exactly what I was thinking about! Thanks, I'll check out it out!
Since you work on the v2 version, this follow-up could be non-relevant, but still worse to mentions. I found logical incorrectness in the results calculations in #23 commit: After exploring the math under the "short put" strategy, it seems that the algorithm is to sell a put (open position) at the bid price, and closing (buying position back) at the ask. This approach is a bit too "conservative" considering that you almost always can establish the position at the (bid+ask)/2 for the major stocks.
In fact, all positions for "short put" and "short call" was terminated by buying the option back from the market, whereas it should be terminated worthless with $0.00 cost.
Summarizing the above, here's two additional suggestions:
Thanks!
You are correct, I will address this issue in the update. Thanks for catching that!
Hi Michael,
I've been testing your module for some time and came up with an improvement idea. Most of my actual strategies are tied to additional external data like VIX, stocks' earnings, etc.
Adding the ability to consider exogenous variables to the strategy will dramatically increase the efficiency and the value of your system.
It could be done by allowing custom columns in the initial dataframe:
And initial filters to be like for example:
If it could be implemented, then your module could be used to find patterns not only in historical option prices but also across a variety of financial instruments.