Comments (6)
Hi @edtechre
I tried your code, but it still doesn't work, no trade happens.
So I made some changes to your code based on my understanding of ATR Trailing Stop.
I list code below, in case anyone needs it.
def exec_fn(ctx: ExecContext):
if ctx.long_pos():
stop = ctx.session.setdefault(
"stop",
ctx.close[-1] - ctx.indicator("atr_100")[-1] * 2
)
stop = max(
stop,
ctx.close[-1] - ctx.indicator("atr_100")[-1] * 2,
)
if ctx.low[-1] <= stop:
ctx.sell_all_shares()
del ctx.session["stop"]
else:
ctx.session["stop"] = stop
elif ctx.short_pos():
stop = ctx.session.setdefault(
"stop",
ctx.close[-1] + ctx.indicator("atr_100")[-1] * 2
)
stop = min(
stop,
ctx.close[-1] + ctx.indicator("atr_100")[-1] * 2,
)
if ctx.high[-1] >= stop:
ctx.cover_all_shares()
del ctx.session["stop"]
else:
ctx.session["stop"] = stop
else:
# some buy/long or sell/short code here
pass
from pybroker.
Hi @none2003,
The field stop_trailing will behave just like stop_trailing_pct, except the units are set in absolute price points.
The reason the code isn't working is that the stop is created when the entry is created (i.e., ctx.buy_shares) and cannot be updated afterwards because each stop only applies to its associated entry.
To support your case of dynamically updating the stop, I can add support for setting a Callable that would return the points amount based on the current context (e.g., ATR).
In the meantime, you can determine if a stop is hit by checking ctx.long_pos() and ctx.high. Additionally, you can then update and save the stop threshold in ctx.session to achieve the trailing behavior.
from pybroker.
After considering this further, I have come to the conclusion that introducing support for dynamic stop values using Callables would make the API confusing. The desired behavior can already be achieved using the execution function. Because stop thresholds are intended to be static, I have implemented checks to prevent your example from failing silently. Instead, it will now throw an error.
To achieve what you are after, you can reference this code:
import pybroker as pyb
import talib
def exec_fn(ctx):
if ctx.long_pos():
stop = ctx.session.setdefault(
"stop",
ctx.high[-1] - ctx.indicator("atr_100")[-1] * 2
)
if ctx.low[-1] <= stop:
ctx.sell_all_shares()
del ctx.session["stop"]
else:
ctx.session["stop"] = max(
stop,
ctx.high[-1] - ctx.indicator("atr_100")[-1] * 2,
)
else:
ctx.buy_shares = ctx.calc_target_shares(1)
atr_100 = pyb.indicator("atr_100", lambda data: talib.ATR(data.high, data.low, data.close, timeperiod=100))
strategy.clear_executions()
strategy.add_execution(exec_fn, ['TSLA'], indicators=atr_100)
result = strategy.backtest(warmup=100)
Let me know if you need anything else!
from pybroker.
Whether a trade is made is going to depend on the data you're using for the backtest. My example uses the daily high price instead of close for updating the stop, and it placed trades for my dataset. But glad you have something working, thanks for sharing!
from pybroker.
After considering this further, I have come to the conclusion that introducing support for dynamic stop values using Callables would make the API confusing. The desired behavior can already be achieved using the execution function. Because stop thresholds are intended to be static, I have implemented checks to prevent your example from failing silently. Instead, it will now throw an error.
To achieve what you are after, you can reference this code:
import pybroker as pyb import talib def exec_fn(ctx): if ctx.long_pos(): stop = ctx.session.setdefault( "stop", ctx.high[-1] - ctx.indicator("atr_100")[-1] * 2 ) if ctx.low[-1] <= stop: ctx.sell_all_shares() del ctx.session["stop"] else: ctx.session["stop"] = max( stop, ctx.high[-1] - ctx.indicator("atr_100")[-1] * 2, ) else: ctx.buy_shares = ctx.calc_target_shares(1) atr_100 = pyb.indicator("atr_100", lambda data: talib.ATR(data.high, data.low, data.close, timeperiod=100)) strategy.clear_executions() strategy.add_execution(exec_fn, ['TSLA'], indicators=atr_100) result = strategy.backtest(warmup=100)
Let me know if you need anything else!
I have a question about the timing of the trailing stop trigger in pyb. If ctx.buy_shares is executed along with ctx.stop_trailing_pct.
My understanding is that pyb calculates a stop loss level for each bar, so question 1, this stop loss level is calculated based on what price minus stop_trailing_pct? high[-1]?
Once the price of a bar falls below this stop level, then the stop loss will be triggered, so question 2, which of the ohlc specifically falls below the stop level and triggers the stop loss?
Question 3, after the stop is triggered, is the timing for the order to be fulfilled at the moment it is triggered, or at the next bar? This is related to the code you provided above, in your code, the trailing stop order will be fulfilled at the next bar, rather than at the moment stop loss was trigged.
Question 4, if it is at the next bar, which of the ohlc will be the price to fulfill tailing stop order?
from pybroker.
Hi @none2003,
My understanding is that pyb calculates a stop loss level for each bar, so question 1, this stop loss level is calculated based on what price minus stop_trailing_pct? high[-1]?
Yes, high for long positions, and low for short positions.
Once the price of a bar falls below this stop level, then the stop loss will be triggered, so question 2, which of the ohlc specifically falls below the stop level and triggers the stop loss?
Stop losses on long positions will check if the stop has fallen below the current bar's low price, high for short positions.
Question 3, after the stop is triggered, is the timing for the order to be fulfilled at the moment it is triggered, or at the next bar? This is related to the code you provided above, in your code, the trailing stop order will be fulfilled at the next bar, rather than at the moment stop loss was trigged.
Using the built-in stops, the stop will be filled on the current bar when it is triggered, and will be filled at the stop value. See the _trigger_stop method in portfolio.py: https://github.com/edtechre/pybroker/blob/master/src/pybroker/portfolio.py#L1171
You could simulate the same fill price by setting ctx.sell_fill_price.
from pybroker.
Related Issues (20)
- Multi-timeframe? HOT 2
- Indicator might be wrong when applying filter on backtesting data HOT 2
- Add MAE (Maximum Adverse Excursion) and MFE (Maximum Favorable Excursion) metrics. HOT 1
- Add regular defined contribution to portfolio HOT 1
- Add Ruff for Python linter and code formatter HOT 3
- Real-time question HOT 1
- The feature names should match those that were passed during fit HOT 6
- [Feature] Add support for Schwab HOT 2
- 设置了ctx.score的值后,买入的具体原则是怎样的,这个ctx.score具体作用和影响是什么呢 HOT 1
- How to set a different ctx.sell_fill_price HOT 1
- Walkforward questions HOT 1
- Question from the Rebalancing example HOT 1
- About update numpy to 2.0 HOT 4
- Can ctx.score work with ctx.sell_shares? HOT 1
- when use stop loss, how to get callback while trigger stop action HOT 1
- AlpacaCrypto Object is not callable HOT 1
- caching data bug in month or week frequence HOT 2
- AKShare got an unexpected keyword argument 'timeframe' HOT 3
- Rotational Trading not working when using start_of_month HOT 1
- [Question] symbol for indicator but not for trading HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from pybroker.