Closed booboothefool closed 4 years ago
I will look into this, but for now, use trailamount. There was an issue, why I did not add trailpercent, but don't really remember why.
Thanks I really appreciate it! However now that I let it run on paper trade for a bit, it seems like i can't get a StopTrail
even with just trailamount
to fully Completed
at all. It is able to place the order e.g. a bracket of Stop+StopTrail+TakeProfit or a Market+StopTrail+TakeProfit are Submitted
, but the entry Stop/Market order appears to get Rejected
every time if it is paired with a StopTrail.
2020-05-18 14:06:05 | Stop Order | GBP/USD | 7 | Buy | 1.21986 | 1.22178 | 1.21922 | | | | | |
-- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | --
2020-05-18 14:06:05 | Stop Order | GBP/USD | 7 | Buy | 1.21986 | 1.22114 | 1.21922 | | | | | |
^ without `stopexec=bt.Order.StopTrail`
v with `stopexec=bt.Order.StopTrail`
2020-05-18 13:54:45 | Market Order Reject | | | | | | | | | | | |
2020-05-18 13:54:45 | Market Order Reject | | | | | | | | | | | |
2020-05-18 13:41:25 | Stop Order Reject | | | | | | | | | | | |
2020-05-18 13:41:25 | Stop Order Reject
The Rejected
Stop and Market orders you see there used:
self.long_order2 = self.buy_bracket(exectype=bt.Order.Stop, stopexec=bt.Order.StopTrail, size=qty,
limitprice=TP2_price,
price=entry_price,
# stopprice=stoploss_price,
stopargs={
'trailamount': stop_dist,
},
)
self.long_order2 = self.buy_bracket(exectype=bt.Order.Market, stopexec=bt.Order.StopTrail, size=qty,
limitprice=TP2_price,
price=entry_price,
# stopprice=stoploss_price,
stopargs={
'trailamount': stop_dist,
},
)
The orders that were Accepted
used:
self.long_order2 = self.buy_bracket(exectype=bt.Order.Stop, size=qty,
limitprice=TP2_price,
price=entry_price,
stopprice=stoploss_price,
# stopargs={
# 'trailamount': stop_dist,
# },
)
Note that I removed stopexec=bt.Order.StopTrail
to get it to go through, but of course now I don't have the trailing stop that I want. stop_dist
is just a value like 0.0003 for 3 pips.
I am not sure if the issue is related or if it's supposed to work and I just did my input wrong, however everything worked perfectly during backtesting. Is there a way to log out the actual errors Oanda API is sending? That would probably reveal what the issue is.
The order is rejected mostly because of a too close trail stop (GBP/USD is 5 pips I think)
Oh, you're right. I see it's actually happening on a few of my regular non-StopTrail orders too. Also it's trading the 5 second chart so the price and calculated stop locations might have moved by the time it gets a signal and tries to create an order. Makes sense. Are there some docs somewhere on the minimum stop requirements so I can make sure I'm in bounds?
But wow, even though it doesn't even work properly as I intended, it's actually still profitable! Thanks a bunch!
you can check the trailing stop distance with the data from contract details of the feed:
data.contractdetails['minimumTrailingStopDistance']
and
data.contractdetails['maximumTrailingStopDistance']
the value should be in pips, for the pip location you can use:
data.contractdetails['pipLocation']
#
# The location of the “pip” for this instrument. The decimal position of
# the pip in this Instrument’s price can be found at 10 ^ pipLocation (e.g.
# -4 pipLocation results in a decimal pip position of 10 ^ -4 = 0.0001).
#
pipLocation : (integer),
#
# The maximum trailing stop distance allowed for a trailing stop loss
# created for this instrument. Specified in price units.
#
maximumTrailingStopDistance : (DecimalNumber),
#
# The minimum trailing stop distance allowed for a trailing stop loss
# created for this instrument. Specified in price units.
#
minimumTrailingStopDistance : (DecimalNumber),
See also:
https://developer.oanda.com/rest-live-v20/primitives-df/ Instrument definition
i have committed a implementation for the trailpercent, please check this and give me some feedback for it. Thanks
I believe it worked! With this code:
self.long_order2 = self.buy_bracket(exectype=bt.Order.Stop, stopexec=bt.Order.StopTrail, size=qty,
limitprice=TP2_price,
price=entry_price,
# stopprice=stoploss_price,
stopargs={
# 'trailamount': stop_dist,
# 'trailpercent': 0.01,
'trailpercent': 0.02,
},
)
File "/usr/local/lib/python3.7/site-packages/btoandav20/stores/oandav20store.py", line 385, in order_create
'.%df' % order.data.contractdetails['displayPrecision']),
TypeError: unsupported format string passed to NoneType.__format__
Error no longer appears and the order goes through! 👍
I wonder if this is intended behavior - in TradingView it does not show up under "Trailing Stop" but just spam many "Stop". Maybe somewhere Oanda/Backtrader/library it doesn't understand that it is "Trailing Stop" so it just updates by creating more orders? I think it's ok?
Oh well, I did notice it increased the profit of my winning strategy, so I am very happy! Soon I will be able to quit my day job! Just have to learn how to calculate pips so I can increase quantity of trade... I'm new to trading and FOREX and 0.001 pip is very confusing to me!! 💸🎉
Do you know if it is possible to add ATR trailing stop? For example:
self.atr = bt.ind.ATR()
'trailamount': self.atr[0]
Or that only set the first distance and it just uses only that distance? It does not dynamically calculate the new ATR every time it moves, does it? Cause that would be amazing and even more profit! If not, it is no problem. Thank you very much!
for the atr value, it will not update the created order. if you want to update an existing order, you would need to cancel them manually and create new ones.
will check the new code later and close this issue if it works probably.
Oh well, I did notice it increased the profit of my winning strategy, so I am very happy! Soon I will be able to quit my day job! Just have to learn how to calculate pips so I can increase quantity of trade... I'm new to trading and FOREX and 0.001 pip is very confusing to me!! 💸🎉
just be careful, since test code may generate different results than reallife code execution. hope the best for your strategies.
for pips calculations, the value from
data.contractdetails['pipLocation']
is useful, when calculating pips for different instruments. also check out the different sizers, which provides position size calculations based on risk percent or risk amount.
https://github.com/ftomassetti/backtrader-oandav20/blob/master/btoandav20/sizers/oandav20sizer.py
Yes, I understand. Backtest seems too optimistic and inaccurate so unreliable, however I've noticed paper trade is close enough to the real result. I watched it trade all day today and was very happy with the performance so far, so it shows promise and I think it will continue. It is very consistent and manages risk well, so could also easily lose 10x trades in a row and still be safe. I am hopeful, thanks!
And thanks for the tips about the pips and sizers! Yes I was wondering about that cause EUR/USD USD/JPY, etc. Very happy!
Don't risk more than 1%!!! 🥇
I like this attitude. Wish you a lot of luck. Will check the trailpercent and close this issue.
Oh, actually I made mistake earlier. The picture I showed of all "Stop" orders was actually "Stop". When "StopTrail" is completed successfully, it should show up under "Trailing Stop" column like this: So it looks like it works! 👍
Had questions though after seeing the implementation at https://github.com/ftomassetti/backtrader-oandav20/commit/ef0fc2c746af2236a52fb2eff0c2dd70321b042f#diff-fbbb1d2f4d23dc3fcd8e4fcb14b21e17R378 Does thetrailpercent
here update to new price difference whenever it moves, or does it just take the first price and use that only similar to how ATR stop can't update?
So if trail by 1%, which one? A: (99) 100 -> (108.9) 110 or B: (99) 100 -> (109) 110
I would like it to do A, but it looks like it might be doing B.
https://www.backtrader.com/docu/order-creation-execution/trail/stoptrail/ Also it looks like backtrader uses decimals e.g. 0.01. (100 price / 100) * 0.01 = 0.01 trailamount = 100 - 0.01 = 99.99 seems too small
So it looks like in your code you use percentage like 1%: (100 price / 100) * 1 = 1 trailamount = 100 - 1 = 99
Is this intentional or did you mean to match the backtrader and use 0.01 format? Thanks!
I changed the calculation to just do price * trailpercent, so it will use 0.01 for 1 percent. also it will never change the amount, when the order is sent, it won't be changed anymore.
Just a comment. I noticed even though self.data.contractdetails['minimumTrailingStopDistance'] = 0.0005
,
'trailamount': 0.0003
still works sometimes. I am not sure why.
Will close this issue, since it seems to be working
Using
trailamount
seems to be ok, buttrailpercent
gives error.At a glance, it looks like there might not be support for trailing stop by percent? https://github.com/ftomassetti/backtrader-oandav20/blob/master/btoandav20/stores/oandav20store.py#L384 If so, could it be added?
Thank you for the library! 👍