Regular Strategy Guide
Regular Strategy Guide
Initial steps
Below are the initial steps
-
Naming a Class
eg: For the above strategy name the class name would be:
StrategyFuturesEMACrossover(StrategyBase)
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 strategy is a child class of the StrategyBase class.
-
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 = 'futures_ema_crossover'
Init method
This method gets called only once when the strategy is started.
-
Strategy info
In the init method add the line given below
super().__init__(*args, **kwargs)
-
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.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 be different for different strategies.
-
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
-
Strategy variables
We create our own strategy variables other than the strategy parameter variables which will be used throughout the strategy.
eg:
self.order_tag_manager = None
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:
-
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
.
- Stores the order object for the given tags.
-
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
- Retrieve the order(s) for the given tags.
-
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 theOrderTagManager
.
- Removes the tags stored in the
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 the order tags.
-
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 theOrderTagManager
. - Remove the order(s) from the
Note
The order object will be removed from all the tags ta
-
get_internals
- Returns the values i.e. both the entry and exit orders stored inside the tags list.
Entry Methods
Following are the entry methods.
-
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 an
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
toselected_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
-
-
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
-
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.
-
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:
-
check_and_place_stoploss_order
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. -
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 theself.main_order
variable.
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 Regular strategies
- Aroon Crossover
- Bollinger Bands
- EMA Crossover
- Inverse EMA Scalping
- Reverse RSI
- Stochastic Crossover
- VWAP Crossover
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.