Option Strategy Structure
Initial steps
The Initial Steps guide you through setting up your strategy in Phoenix Web, focusing on naming conventions for both the strategy class and its displayed name.
i) Naming a Class
eg: For the above strategy name the class name would be:
StrategyOptionsEMACrossover(StrategyOptionsBaseV2)
Tip
Coding Conventions
- Make a class with the same name as the file name
- Make sure the first letter of each word is in uppercase and the initials should be in uppercase as well.
- If the class name includes indicator names like EMA, SMA, and VWAP the name should be in uppercase in the class name but not in the file name.
- Every options strategy is a child class of the StrategyOptionsBaseV2 class.
ii) Naming your Strategy
This name will be displayed in your My Coded Strategies in Phoenix Web, and it will also be the strategy_name when you are fetching all strategies in pyalgotrading.
Inside your strategy class, you can write your first parameter as name
.
name = 'options_ema_crossover'
Init method
This method gets called only once when the strategy is started.
i) Strategy info
In the init method add the line given below
super().__init__(*args, **kwargs)
ii) Parameter creation
Next, we assign the parameter values to the class variables of the same name as the parameters but in the lowercase format as shown below:
eg:
self.fresh_order_candle = self.strategy_parameters['FRESH_ORDER_CANDLE']
self.start_time_hours = self.strategy_parameters['START_TIME_HOURS']
self.start_time_minutes = self.strategy_parameters['START_TIME_MINUTES']
self.end_time_hours = self.strategy_parameters['END_TIME_HOURS']
self.end_time_minutes = self.strategy_parameters['END_TIME_MINUTES']
self.no_of_strikes_away_ce = self.strategy_parameters['NO_OF_STRIKES_AWAY_CE']
self.no_of_strikes_away_p = self.strategy_parameters['NO_OF_STRIKES_AWAY_PE']
self._strike_direction_ce = self.strategy_parameters['STRIKES_DIRECTION_CE']
self._strike_direction_pe = self.strategy_parameters['STRIKES_DIRECTION_PE']
self.ema_period_one = self.strategy_parameters['EMA_PERIOD_ONE']
self.ema_period_two = self.strategy_parameters['EMA_PERIOD_TWO']
self.target_percentage = self.strategy_parameters['TARGET_PERCENTAGE']
self.stoploss_percentage = self.strategy_parameters['STOPLOSS_PERCENTAGE']
self.stoploss_range = self.strategy_parameters['STOPLOSS_RANGE']
self.stoploss_order_count_allowed = self.strategy_parameters['STOPLOSS_ORDER_COUNT_ALLOWED']
Note
The parameter names and the number of parameters may change for different strategies.
iii) Start time and End time creation
Adding Start and End time is useful when you want to define a timerange between which the strategy will be running each day.
Add the below code to calculate the strategy start time and end time, from the strategy_parameters
.
try:
self.candle_start_time = time(hour=self.start_time_hours, minute=self.start_time_minutes)
except ValueError:
self.logger.fatal('Error converting start hours and minutes... EXITING')
raise SystemExit
try:
self.candle_end_time = time(hour=self.end_time_hours, minute=self.end_time_minutes)
except ValueError:
self.logger.fatal('Error converting end time hours and minutes... EXITING')
raise SystemExit
iv) Start time and End time creation
We create our own strategy variables other than the strategy parameter variables which will be used throughout the strategy.
eg:
self.main_order = None # We save the entry order in this variable
self.stoploss_order = None # We save the corresponding stoploss exit order of the entry order in this variable
We initialize the variables with a None value.
Note
There could be more strategy variables required as per the strategy requirement.
Initialize method
Unlike the init method
, this method gets called every day at the beginning of the day once the strategy is started.
Here the strategy variables that were initialized as None are again defined as dictionaries/lists except for the self.order_tag_manager
.
Create a reference for OrderTagManager
as shown below:
self.order_tag_manager = OrderTagManager
OrderTagManager
The self.order_tag_manager
is used to store/remove the entry/exit orders. The self.order_tag_manager
has the following methods:
i) add_order
- Stores the order object for the given tags. eg:
self.order_tag_manager.add_order(_order, tags=[base_inst_str, entry_key])
- Here the
_order
is the order object stored inside theOrderTagManager
for the tagsbase_inst_str
andentry_key
.
ii) get_orders
- Retrieve the order(s) for the given tags.
eg:
self.order_tag_manager.get_orders(tags=[base_inst_str, BrokerExistingOrderPositionConstants.ENTER, entry_key], ignore_errors=True)
- Here the order object retrieved from the
OrderTagManager
for the tagsbase_inst_str, BrokerExistingOrderPositionConstants.ENTER
andentry_key
iii) remove_tags
- Removes the tags stored in the
OrderTagManager
along with the orders related stored in that tag
eg:
self.order_tag_manager.remove_tags(tags=entry_key)
Here the entry_key
tag is removed from the OrderTagManager
.
Note
When the tag is removed the order objects stored in that tag are also removed but the same order objects would still be present in order tags.
iv) remove_order
- Remove the order(s) from the
OrderTagManager
for the given tag(s).
eg:
self.order_tag_manager.remove_order(main_order)
Here the main_order
order object is removed from the OrderTagManager
.
Note
The order object will be removed from all the tags ta
v) get_internals
Returns the values i.e. both the entry and exit orders stored inside the tags list.
Child instruments calculation
i) get_ltp
Fetch the ltp of the base instrument (instrument set while executing strategy)
ltp = self.broker.get_ltp(self.underlying_instrument)
iii) options_instruments_set_up_local
Get the ATM ITM and OTM lists of the child instrument based on the LTP
self.options_instruments_set_up_local(self.underlying_instrument, tradingsymbol_suffix, ltp)
iii) get_child_instrument_details
Select a child instrument from the lists of ATM, ITM, and OTM based on the strike direction and no of strikes given for the child instrument
child_instrument = self.get_child_instrument_details(self.underlying_instrument, tradingsymbol_suffix, strike_direction, no_of_strikes)
Entry Methods
i) strategy_select_instruments_for_entry
-
In this method we process each instrument in the instruments bucket, if there is some entry condition to be checked then we create a
get_entry_decision
method that calculates the entry condition like a crossover or compares the latest value of the OHLC data or indicator data. -
When the order has to be placed we add the
instrument
toselectd_instruments_bucket
and additional data related to the instrument that will be required while placing to thesideband_info
. This information is passed to thestrategy_enter_position
method
ii) strategy_enter_position
- Here is where we actually place the entry order for which we calculate the quantity for the order to be placed. If the order is placed successfully we save the order in a class variable such that we can access the order object via the variable in the exit methods.
Exit Methods
i) strategy_select_instruments_for_exit
- This method is called before the entry methods because in the case of delivery strategy we want to resume and exit previous day orders before we can place new entry orders.
- Here we place stoploss exit orders, target exit orders, and check for exit conditions for the open entry orders.
ii) strategy_exit_position
- Here is where we actually place the exit order for where we exit the order which was placed during entry. If the order is placed successfully we clear the order in a class variable such that we can add new orders to the vacant place in variable in the entry methods.
Other common methods
There are other methods that are used in the strategy:
i) check_and_place_stoploss_ord
A quick guide to coding options strategies in Phoenix Web, covering naming conventions, entry/exit methods, and key strategy functions.er**
This method is called in the strategy_select_instruments_for_exit
when our entry order is open, and we want to place a stoploss exit order for the same.
ii) set_all_none
This method is called in the strategy_exit_position
when our entry order has exited, and we want to remove the order object from the self.main_order
variable.
iii) options_instruments_set_up_local
This method is called in the strategy_select_instruments_for_entry
to fetch the ATM, ITM, and OTM lists of the child instruments based on the LTP of the base instrument.
iv) get_child_instrument_details
This method is called in the strategy_select_instruments_for_entry
to fetch a single child instrument based on the no of strikes and strike direction.
Cleanup
- Add comments and docstrings wherever possible to improve code readability.
- Once the strategy is completed you can optimize imports, give proper indentation and proper formatting to the strategy code and remove unwanted imports, variables, and methods before delivering the code.
Check out our docs for developed Options strategies
- Options Bear Call Ladder
- Options Bear Put Ladder
- Options Bull Call Ladder
- Options Bull Put Ladder
- Options Long Iron Butterfly
- Options Straddle
- Options Strangle
Tip
To know more about a strategy from our given template, simply check the first line of comment in the code of that specific strategy.