Filter functions are used to filter out bad trades.
First, add the
filters() method to your strategy class which must return a list:
def filters(self): return 
Then define filter methods as many as you need. They can have any name, but it is recommended to include the word
filter in it:
def filter_1(self): return abs(self.price - self.long_EMA) < abs(self.price - self.longer_EMA)
And then add the method's object to the
filters method's list:
def filters(self): return [ self.filter_1 ]
Notice that you must only add the method's object to the list. Do not call the method! (no parentheses at the end of the method name)
def filters(self): return [ self.filter_1() ]
There are two reasons for using them:
1. To keep entry rules clean
Having so many conditional statements in
should_short() is not good practice.
You should keep your entry rules as simple as possible. You can then add filters per each special condition that you would like to avoid.
2. Filters have access to entry and exit points
Entry rules are defined in
should_short() functions; however entry and exit points are defined in
go_short() functions. That means if you need to evaluate a condition based on entry and exit points, you have to do it in a filter instead.
They say a picture worths a thousand words:
For example let's write a filter that makes sure the minimum PNL for trades is bigger than 1%:
def minimum_pnl_filter(self): reward_per_qty = abs(self.average_take_profit - self.average_entry_price) pnl_percentage = (reward_per_qty / self.average_entry_price) * 100 return pnl_percentage > 1
Notice that we are using
self.average_take_profit properties which were not available inside
3. Easier debugging
When a filter prevents opening a trade by not passing, it gets logged.
At the moment Jesse only supports backtesting so you need to run your backtests with
--debug flag to see the logged message for filters. Later, when the live trade plugin is released, this will make a difference in your live strategies too.