Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

position.close() and stop loss features #1018

Answered by peacerider
huytradingz asked this question in Q&A
Discussion options

Hello all, I am fairly new to trading, backtesting and backtesting.py in general, I would like know more about two things:

  1. When you call position.close() after certain conditions are met, what exactly will position.close() do?
  2. I am coding a ema crossover strategy for backtesting that implements both a stop loss and trailing stop loss and would like to know if this is a logical way to do it. I want to set my stop loss at 1RR and a trailing stop loss at a set percentage of the price. Here is what I have done:

`class EmaCross(Strategy):
#EMA candles
w1 = 5
w2 = 21

#Set stop loss and take profit percentage for long and short orders
stop_loss = 5 
take_profit = 10 
stop_loss_short = 4 
take_profit_short = 8 
#Modify indicators for strategies here
def init(self):
 #Calculate two EMAs 
 self.ema1 = self.I(ta.EMA, self.data.Close, self.w1) 
 self.ema2 = self.I(ta.EMA, self.data.Close, self.w2)
 #Calculate RSI 
 self.RSI = self.I(ta.RSI, self.data.Close)
 
#Define your strategy here
def next(self):
 price = self.data.Close[-1]
 riskpertrade = 0.03 * 1000000 #risk allowed * balance
 takeprofit = price + price*self.take_profit/100
 takeprofit_s = price - price*self.take_profit_short/100
 
 stoploss = price - price*self.stop_loss/100
 stoploss_s = price + price*self.stop_loss_short/100
 
 #Order size can be negative (short), sell() won't take in negative values
 order_size = abs(int(riskpertrade/(price - stoploss)))
 order_size_s = abs(int(riskpertrade/(price - stoploss_s)))
 
 if (crossover(self.ema1, self.ema2) and
 self.RSI > 50):
 self.position.close()
 self.buy(tp = takeprofit,
 sl = stoploss,
 size = order_size)
 
 elif (crossover(self.ema2, self.ema1) and
 self.RSI < 50):
 self.position.close()
 self.sell(tp = takeprofit_s,
 sl = stoploss_s,
 size = order_size_s)`

Thank you in advance!

You must be logged in to vote

Hi,

Thank you for your explanation. I understood.

Your trailing stop is not working.
Once the order (buy or sell) is done, the stop loss of backtesting.py "sl" is not changed until the position is closed.

If you want to change the stop loss level to always be 5% of price.
You need to change the "sl" parametor of "trades".
https://kernc.github.io/backtesting.py/doc/backtesting/backtesting.html#backtesting.backtesting.Strategy.trades

Example

# set a pl/tp (trailing stop)
if len(self.trades) > 0 and self.trades[0].is_long:
 self.trades[0].sl = price - price*self.stop_loss/100
 self.trades[0].tp = price + price*self.stop_loss/100
elif len(self.trades) > 0 and self.trades[0].is_short:
 ...

Replies: 1 comment 7 replies

Comment options

You must be logged in to vote
7 replies
Comment options

Thank you for your help! Have you got a chance to look at the code I have written? Logical wise, do you think that is the way to code what I want?

Thank you so much!

Comment options

Hi,
It looks like there is no particular problem.
But I could't find "a trailing stop loss at a set percentage of the price" in your code.

Comment options

Hi there,

Sorry for the confusion, I have set the stop loss and take profit percentage here:

stop_loss = 5 take_profit = 10 stop_loss_short = 4 take_profit_short = 8

And for the trailing:

stoploss = price - price*self.stop_loss/100 stoploss_s = price + price*self.stop_loss_short/100

I wrote this to set the stop loss to always be 5% of price. Do you think this is logically correct?

Comment options

Hi,

Thank you for your explanation. I understood.

Your trailing stop is not working.
Once the order (buy or sell) is done, the stop loss of backtesting.py "sl" is not changed until the position is closed.

If you want to change the stop loss level to always be 5% of price.
You need to change the "sl" parametor of "trades".
https://kernc.github.io/backtesting.py/doc/backtesting/backtesting.html#backtesting.backtesting.Strategy.trades

Example

# set a pl/tp (trailing stop)
if len(self.trades) > 0 and self.trades[0].is_long:
 self.trades[0].sl = price - price*self.stop_loss/100
 self.trades[0].tp = price + price*self.stop_loss/100
elif len(self.trades) > 0 and self.trades[0].is_short:
 self.trades[0].sl = price + price*self.stop_loss_short/100
 self.trades[0].tp = price - price*self.stop_loss_short/100

*trades[0] can be trades[0] or trades[-] if the number of valid trades is 1.

def next(self):
 price = self.data.Close[-1]
 riskpertrade = 0.03 * 1000000 #risk allowed * balance
 takeprofit = price + price*self.take_profit/100
 takeprofit_s = price - price*self.take_profit_short/100
 
 stoploss = price - price*self.stop_loss/100
 stoploss_s = price + price*self.stop_loss_short/100
 
 #Order size can be negative (short), sell() won't take in negative values
 order_size = abs(int(riskpertrade/(price - stoploss)))
 order_size_s = abs(int(riskpertrade/(price - stoploss_s)))
 
 if len(self.trades) > 0 and self.trades[0].is_long:
 self.trades[0].sl = price - price*self.stop_loss/100
 self.trades[0].tp = price + price*self.stop_loss/100
 
 elif len(self.trades) > 0 and self.trades[0].is_short:
 self.trades[0].sl = price + price*self.stop_loss_short/100
 self.trades[0].tp = price - price*self.stop_loss_short/100
 if (crossover(self.ema1, self.ema2) and
 self.RSI > 50):
 self.position.close()
 self.buy(tp = takeprofit,
 sl = stoploss,
 size = order_size)
 
 elif (crossover(self.ema2, self.ema1) and
 self.RSI < 50):
 self.position.close()
 self.sell(tp = takeprofit_s,
 sl = stoploss_s,
 size = order_size_s)`

But above example is not good.
Because, sl or tp are not compared to the current price.
*The trailing stop price should change in one direction (not increase or decrease)

A good example is listed below.
#238

price = self.data.Close[-1]
if buy_condition:
 self.buy(sl=price*.99)
for trade in trades:
 if price / trade.entry_price > 1.01: # Once profit is over >1%
 trade.sl = max(trade.sl, price*.98) # "turn on" -2% trailing SL

This is simple, but very good example.

Sorry for the poor explanation.

Answer selected by huytradingz
Comment options

Thank you for your explanation! I will make sure to implement this! Have a nice one!

Comment options

And just a quick confirmation, when you said my example is not good since the sl and tp are not compared to the current price, I thought that by calculating SL and TP based on current price I have already compared them to the current price?

price = self.data.Close[-1]

stoploss = price - price*self.stop_loss/100

Is this not the correct way to write it?

Thank you for your quick responses!!

Comment options

I'm sorry for confusing.
Your calculation of sl is not problem.

I should have comment "compared to the current tp/sl price" .

It's just my own opinion.
So, please ignore.
Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Category
Q&A
Labels
None yet

AltStyle によって変換されたページ (->オリジナル) /