-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Some questions about take profit (tp) & stop loss(sl) #82
Comments
If the next bar's open price is lower than set stop-loss, for example, the trade is exited immediately at that lower (open) price. Similarly for TP. If this, by chance, doesn't explain the discrepancy you're observing, then it's likely a bug. |
class Strategy(Strategy):
tp_pct = 1.01
def next(self):
self.buy(tp=self.tp_pct * self.data.Close)
bt = Backtest(...)
bt.optimize(tp_pct=np.linspace(1.01, 1.10, 10)) |
I will do some testings to see if this is the case. |
easily optimize any params - awesome,that's why I choose backtesting.py, smart designed, small yet powerful, and relative easier to change/customize (compared to backtrader, I totally lost myself when tring to customize it) |
@kernc is it possible to create a constraint with these abstract parameters? bt.optimize(
profitPer=np.linspace(0.75, 1.25, 50),
stoplossPer=np.linspace(0.50, 1, 50),
maximize='Equity Final [$]',
constraint=lambda p: p.profitPer > p.stoplossPer
) Error:
|
Also isn't it possible to gather the next open price to calculate the stop loss and take profit value more precisely? |
Can you post the full traceback? I see no evident reason it should fail there.
For debugging, maybe via backtesting.py/backtesting/backtesting.py Lines 529 to 531 in b460092
|
Yeah, no problem:
Not exactly, like when you're live trading and place a limit order you can calculate your stop loss and take profit price exactly. Now we are calculating the stop loss and the take profit value based on the current close price, but as you said the trade is based of the next bar's open price. Isn't there an ethical way to calculate the stop loss and the take profit based on the next bar's open price, in order that the loses/wins are closer to when live trading with limit orders? |
Not really. As the strategy |
certain backtest platform uses minute bar as price reference even you are backtesting hourly. That's more accurate but far slower than expected. It's a tradeoff upon one's choice. |
@kernc I think I found a bug related to stop loss / take profit. I've been using ATR to calculate my take profit / stop loss price. But when I use a very small stop loss and a very high take profit which has never been reached for all the placed orders, but I still get a positive win rate (on other strategies I even got higher win rates). I had expected that the win rate would be 0%. Am I missing something? Code: # IMPORTS
import pandas as pd
import numpy as np
from backtesting import Strategy, Backtest
from backtesting.lib import crossover
from backtesting.test import GOOG
from finta import TA
class SmaCrossAtr(Strategy):
timePeriod1= 9
timePeriod2= 14
atrPeriod = 14
atrSlDivisor = 2
atrTpMultiplier = 500
def init(self):
# Make dataframe compatible with finta
df = pd.DataFrame({
'open': self.data.Open,
'high': self.data.High,
'low': self.data.Low,
'close': self.data.Close,
'volume': self.data.Volume},
index=self.data.index)
self.sma1 = self.I(TA.SMA, df, self.timePeriod1)
self.sma2 = self.I(TA.SMA, df, self.timePeriod2)
self.atr = self.I(TA.ATR, df, self.atrPeriod)
def next(self):
price = self.data.Close[-1]
if crossover(self.sma1, self.sma2):
self.buy(sl=price - (self.atr[-1] / self.atrSlDivisor), tp=price + (self.atr[-1] * self.atrTpMultiplier))
elif crossover(self.sma2, self.sma1):
self.sell(sl=price + (self.atr[-1] / self.atrSlDivisor), tp=price - (self.atr[-1] * self.atrTpMultiplier))
# Run backtest
bt = Backtest(GOOG, SmaCrossAtr, commission=0)
bt.run() Results:
|
@kernc Any updates on this bug? |
if crossover(self.sma1, self.sma2):
self.buy(sl=price - (self.atr[-1] / self.atrSlDivisor), tp=price + (self.atr[-1] * self.atrTpMultiplier))
elif crossover(self.sma2, self.sma1):
self.sell(sl=price + (self.atr[-1] / self.atrSlDivisor), tp=price - (self.atr[-1] * self.atrTpMultiplier)) I suspect the moving averages have been crossing over while some of the currently held trades had a positive PnL. That makes them "win" trades even if they didn't hit the TP level. Now with PR #47 merged and somewhat overhauled v0.2.0 released, let's call this bug obsolete. |
When I'm using the buy function with a stop loss / take profit argument I would expect that the order can only be closed on that specific stop loss / take profit price. But when I look at the chart (stop loss=0.66%, take profit=1%), I see that the average negative trade result is around -0.80% with as max -1.14752%. How is this possible?
Also why isn't it possible to optimize the take profit / stop loss rate by using the "optimize" function? Can this be added in a later release? Or can I help contribute?
Backtesting version: 0.1.7
The text was updated successfully, but these errors were encountered: