mirror of
https://github.com/wassname/options_backtester.git
synced 2026-07-12 09:17:22 +08:00
72 lines
2.2 KiB
Python
72 lines
2.2 KiB
Python
import math
|
|
|
|
import numpy as np
|
|
|
|
|
|
class Strategy:
|
|
"""Options strategy class.
|
|
Takes in a number of `StrategyLeg`'s (option contracts), and filters that determine
|
|
entry and exit conditions.
|
|
"""
|
|
def __init__(self, schema):
|
|
self.schema = schema
|
|
self.legs = []
|
|
self.conditions = []
|
|
self.exit_thresholds = (math.inf, math.inf)
|
|
|
|
def add_leg(self, leg):
|
|
"""Adds leg to the strategy"""
|
|
assert self.schema == leg.schema
|
|
leg.name = "leg_{}".format(len(self.legs) + 1)
|
|
self.legs.append(leg)
|
|
return self
|
|
|
|
def add_legs(self, legs):
|
|
"""Adds legs to the strategy"""
|
|
for leg in legs:
|
|
self.add_leg(leg)
|
|
return self
|
|
|
|
def remove_leg(self, leg_number):
|
|
"""Removes leg from the strategy"""
|
|
self.legs.pop(leg_number)
|
|
return self
|
|
|
|
def clear_legs(self):
|
|
"""Removes *all* legs from the strategy"""
|
|
self.legs = []
|
|
return self
|
|
|
|
def add_exit_thresholds(self, profit_pct=math.inf, loss_pct=math.inf):
|
|
"""Adds maximum profit/loss thresholds. Both **must** be >= 0.0
|
|
|
|
Args:
|
|
profit_pct (float, optional): Max profit level. Defaults to math.inf
|
|
loss_pct (float, optional): Max loss level. Defaults to math.inf
|
|
"""
|
|
|
|
assert profit_pct >= 0
|
|
assert loss_pct >= 0
|
|
self.exit_thresholds = (profit_pct, loss_pct)
|
|
|
|
def filter_thresholds(self, entry_cost, current_cost):
|
|
"""Returns a `pd.Series` of booleans indicating where profit (loss) levels
|
|
exceed the given thresholds.
|
|
|
|
Args:
|
|
entry_cost (pd.Series): Total _entry_ cost of inventory row.
|
|
current_cost (pd.Series): Present cost of inventory row.
|
|
|
|
Returns:
|
|
pd.Series: Indicator series with `True` for every row that
|
|
exceeds the specified profit/loss thresholds.
|
|
"""
|
|
|
|
profit_pct, loss_pct = self.exit_thresholds
|
|
|
|
excess_return = (current_cost / entry_cost + 1) * -np.sign(entry_cost)
|
|
return (excess_return >= profit_pct) | (excess_return <= -loss_pct)
|
|
|
|
def __repr__(self):
|
|
return "Strategy(legs={}, exit_thresholds={})".format(self.legs, self.exit_thresholds)
|