Skip to content
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

Trailing pct instead of ATR #223

Closed
riodda opened this issue Jan 8, 2021 · 7 comments
Closed

Trailing pct instead of ATR #223

riodda opened this issue Jan 8, 2021 · 7 comments
Assignees
Labels
enhancement New feature or request Hacktoberfest https://hacktoberfest.digitalocean.com

Comments

@riodda
Copy link

riodda commented Jan 8, 2021

Expected Behavior

Allow trailing with PRC instead of ATR

Actual Behavior

Currently the backtesting allow trailing sels only based on ATR, most of crypto bots works in pct trailing (pct for trailing activation and then pct trailing for position close).

@kernc
Copy link
Owner

kernc commented Jan 8, 2021

This is the whole of TrailingStrategy:

class TrailingStrategy(Strategy):
"""
A strategy with automatic trailing stop-loss, trailing the current
price at distance of some multiple of average true range (ATR). Call
`TrailingStrategy.set_trailing_sl()` to set said multiple
(`6` by default). See [tutorials] for usage examples.
[tutorials]: index.html#tutorials
Remember to call `super().init()` and `super().next()` in your
overridden methods.
"""
__n_atr = 6.
__atr = None
def init(self):
super().init()
self.set_atr_periods()
def set_atr_periods(self, periods: int = 100):
"""
Set the lookback period for computing ATR. The default value
of 100 ensures a _stable_ ATR.
"""
h, l, c_prev = self.data.High, self.data.Low, pd.Series(self.data.Close).shift(1)
tr = np.max([h - l, (c_prev - h).abs(), (c_prev - l).abs()], axis=0)
atr = pd.Series(tr).rolling(periods).mean().bfill().values
self.__atr = atr
def set_trailing_sl(self, n_atr: float = 6):
"""
Sets the future trailing stop-loss as some multiple (`n_atr`)
average true bar ranges away from the current price.
"""
self.__n_atr = n_atr
def next(self):
super().next()
for trade in self.trades:
if trade.is_long:
trade.sl = max(trade.sl or -np.inf,
self.data.Close[-1] - self.__atr[-1] * self.__n_atr)
else:
trade.sl = min(trade.sl or np.inf,
self.data.Close[-1] + self.__atr[-1] * self.__n_atr)

It should be fairly simple to adapt/duplicate one for percent values.

@kernc kernc added the enhancement New feature or request label Jan 8, 2021
@riodda
Copy link
Author

riodda commented Jan 8, 2021

Yup, the trailing strategy only supports ATR multiples, but most of the cyrpto bots trail in percentage would be nice to implement as option for trailing strategy so you can choose between ATR or pct for backtesting the best trailing.

@kernc
Copy link
Owner

kernc commented Jan 8, 2021

As a quick workaround, something like this might work:

def pct_to_atr(pct: float, data: pd.DataFrame):
    """Express `pct` change in units of ATR."""
    assert 0 < pct < 1
    h, l, c_prev = data.High, data.Low, pd.Series(data.Close).shift(1) 
    tr = np.max([h - l, (c_prev - h).abs(), (c_prev - l).abs()], axis=0) 
    atr = np.nanmean(tr)
    return (pct * data.Close.iloc[-1]) / atr

@riodda
Copy link
Author

riodda commented Jan 10, 2021

Actually i would need the oppsite, as with backtesting i can find the optimal atr value for trailing the will have to calculate the equivalent pct for program the bot.
I'll find a solution, thanks anyway.

@kernc
Copy link
Owner

kernc commented Jan 11, 2021

Should be rather easy to invert, something like:

def atr_to_pct(n_atr: float, data: pd.DataFrame):
    """Express `n_atr` in units of ATR as percentage of current price."""
    h, l, c_prev = data.High, data.Low, pd.Series(data.Close).shift(1) 
    tr = np.max([h - l, (c_prev - h).abs(), (c_prev - l).abs()], axis=0) 
    atr = np.nanmean(tr)
    return n_atr * atr / data.Close.iloc[-1]

@zlpatel
Copy link
Contributor

zlpatel commented Jun 12, 2021

I am working on this enhancement.

zlpatel added a commit to zlpatel/backtesting.py that referenced this issue Jun 12, 2021
zlpatel added a commit to zlpatel/backtesting.py that referenced this issue Jun 13, 2021
Add code description and use float type for default percentage value.
zlpatel added a commit to zlpatel/backtesting.py that referenced this issue Jun 13, 2021
zlpatel added a commit to zlpatel/backtesting.py that referenced this issue Jun 13, 2021
zlpatel added a commit to zlpatel/backtesting.py that referenced this issue Jun 13, 2021
zlpatel added a commit to zlpatel/backtesting.py that referenced this issue Jun 13, 2021
zlpatel added a commit to zlpatel/backtesting.py that referenced this issue Jun 13, 2021
zlpatel added a commit to zlpatel/backtesting.py that referenced this issue Jun 13, 2021
zlpatel added a commit to zlpatel/backtesting.py that referenced this issue Jun 13, 2021
@zlpatel
Copy link
Contributor

zlpatel commented Jun 13, 2021

@kernc can you review this change?

zlpatel added a commit to zlpatel/backtesting.py that referenced this issue Jun 15, 2021
zlpatel added a commit to zlpatel/backtesting.py that referenced this issue Jun 15, 2021
zlpatel added a commit to zlpatel/backtesting.py that referenced this issue Jun 15, 2021
@kernc kernc added the Hacktoberfest https://hacktoberfest.digitalocean.com label Oct 7, 2021
@kernc kernc self-assigned this Feb 19, 2025
kernc added a commit that referenced this issue Feb 20, 2025
kernc added a commit that referenced this issue Feb 20, 2025
@kernc kernc closed this as completed in 9938d08 Feb 20, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request Hacktoberfest https://hacktoberfest.digitalocean.com
Projects
None yet
Development

No branches or pull requests

3 participants