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

Initial position adjustment support (DCA) #6079

Merged
merged 118 commits into from
Jan 15, 2022
Merged

Conversation

xataxxx
Copy link
Contributor

@xataxxx xataxxx commented Dec 18, 2021

Summary

Implement position adjustment / stacking / multiple buys of the same pair within a single trade.

Partly solve the issue: #2183 and #1519

Quick changelog

  • Added callback adjust_trade_position to strategy that can indicate if should buy more and how much.
  • Added position_adjustment_enable strategy parameter to enable this feature.
  • Updated documentation to document the usage of said features.

What's new?

Implement ability for strategy to buy more of an already opened trade.
The most common scenario for this would be DCA (Dollar Cost Averaging).
The theory is that your buys signals, while good, sometimes still produce trades that first go down X% and then rise to the profit. With DCA you can buy more of the same coin when it's gone down Y% to increase your stake and lower your average open price. This results in higher probability to reach profit AND faster trade times. It can also produce bigger and more hurtful stoplosses.

Done list:

  • Strategy callbacks to implement DCA logic
  • Additional buy logic to allow DCA
  • Trade open price averaging and total amount summing works
  • Limit orders works but they follow the same timeout rules as the original buy
  • Stoploss on exchange is canceled and new one is created.
  • Backtesting seems to work (HyperOpting also)
  • Documentation is there
  • Unit tests seem to cover basic DCA functionality without breaking other tests

TODO List:

  • FreqUI part is not updated yet, which means if you do buy a pair more than once with a big enough price difference, your initial buy open price is displayed way outside of the candle. Best course of action is to start showing the individual filled orders.
  • Negative adjustment / Partial sell - Not planning on implementing that currently and documentation and comments in code also indicate that we support buy orders not sell orders. A warning is thrown into log when negative price adjustment is attempted.

Copy link
Member

@xmatthias xmatthias left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pretty darn good job 👍

I'm sure we'll discover some edge-cases as more people start using this - but for the moment i'd not know anything more to do on this PR.

LGTM 👍

@xmatthias xmatthias merged commit caea896 into freqtrade:develop Jan 15, 2022
# Total stake for this trade would be 1 + 1.25 + 1.5 + 1.75 = 5.5x of the initial allowed stake.
# That is why max_dca_multiplier is 5.5
# Hope you have a deep wallet!
if 0 < count_of_buys <= self.max_dca_orders:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great job to both of you! I have a question about the select_filled_orders method.

Wouldn't this condition trigger multiple orders if the first order doesn't get filled right away? I think this count should include the potential pyramidal orders created in the last cycle.

As far as I understand, we're counting just filled orders with these statuses which would not select orders we might have already placed at this level and which are still open.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please read the documentation that was added as part of this PR.

this callback will not be called if a order is open.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry I missed it! It might be worth adding it to the function docstring as well.

@umutrcc
Copy link

umutrcc commented Jan 15, 2022

Will we be able to do partial trading now? How to use it, can you share a detailed usage or a sample study? thank you.

@rokups
Copy link
Contributor

rokups commented Jan 16, 2022

https://www.freqtrade.io/en/latest/strategy-callbacks/#adjust-trade-position

@ghost
Copy link

ghost commented Jan 25, 2022

This is a nice feature, but i don't think the example is very useful because profitable trades will only have a small stake, which means only small profits on these trades and losing trades will have high stakes, which means much higher losses are possible.
Maybe using buy signals from strategy to buy more coins would be better, but i don't think it is possible at the moment because pairs with open trades won't be analyzed by the bot - so maybe changing this would be a good idea?

@rokups
Copy link
Contributor

rokups commented Jan 25, 2022

Point of example is to demonstrate how to use this feature. Profitability of samples is really out of scope of technical documentation.

@ghost
Copy link

ghost commented Jan 25, 2022

Ok, but do you think we can use additional buy signals to adjust positions?

@stash86
Copy link
Contributor

stash86 commented Jan 25, 2022

Anything is possible if you know how to code it

@rokups
Copy link
Contributor

rokups commented Jan 25, 2022

Signal adjustment callback runs on each candle. You may access dataframe from this callback and see if last candle has your signal. See here https://www.freqtrade.io/en/stable/strategy-advanced/#dataframe-access

@ghost
Copy link

ghost commented Jan 25, 2022

Thank you for your reply, this was very helpful.
With this i can access all indicators of the strategy, so i just have to put the code for my buy signal inside populate_indicators and can then use that to adjust positions.

@perkmeister
Copy link

This post on Discord may help you @incrementby1. As an aside, backtesting is broken if you remove the current_profit check @xmatthias
https://discord.com/channels/700048804539400213/920652305936842752/934926696195444756

@xmatthias
Copy link
Member

That link kindof leads to the rules channel ... so not "quite" sure what you're trying to point me to ...

@perkmeister
Copy link

Oh sorry, its the Freqtrade Discord server, my post regarding using buy signals (or other dataframe signals) to trigger DCA buys individually. I'll fill in a github issue report regarding the backtesting.

@perkmeister
Copy link

perkmeister commented Jan 26, 2022

That link doesn't open properly, yet it's the link copied directly from the post (in the DCA thread). Odd... Anyway, do a search for DCATest2_fixed.py on Discord.

@xataxxx
Copy link
Contributor Author

xataxxx commented Jan 27, 2022

A note to those who might read it later - "backtesting is broken if you remove the current_profit check" is wrong, everything works as expected. If you remove current_profit then you'll just end up buying until you run out of money. It's the responsibility of adjust_trade_position to decide if it's the right moment to buy more - if you don't check your current profit then you better check something else and do not return a stake amount if you don't want to buy.

@perkmeister
Copy link

True, but there is no difference between that and failing the current_profit check on all DCA buys. In backtesting this would fail, in live/dry it behaves correctly as it buys as much as it can with DCA and holds the trades open.

@perkmeister
Copy link

@xataxxx If you think backtesting isn't broken, run this simple strategy that just buys 3 times then sells and repeats. It should not (IMO) immdiately close trades with a profit of -0.2%, the user is in complete control with max_dca_orders and max_dca_multiplier, it should just buy the max it can and leave the trade open just like it does in live or dry. I'm concerned this is highlightng an underlying logical issue that might show itself if a current_profit check were to fail for each DCA buy, and if adjust_trade_position() is called once per candle and current_profit is the open rate of the next candle this is entirely possible. I may of course be misinterpreting things, but maybe you could explain why this behaviour shows it 'works as expected'?
DCATest2_broken.py.TXT

@xmatthias
Copy link
Member

xmatthias commented Jan 28, 2022

@perkmeister

If you think something is broken, please open an issue with all necessary details (this includes a simple strategy to reproduce the problem, but also output that's produced by it, the command used for this (if necessary some config), and maybe a description what you'd expect and what happened.

Based on the above comment, you'd expect us to first investigate what's actually happening, while then comparing it what you think would happen - which will quite frankly - simply waste our time.

@xataxxx
Copy link
Contributor Author

xataxxx commented Jan 28, 2022

Just for info for future readers, @perkmeister issue was actually caused by another tiny temporary bug in codebase that disabled adjust_trade_position completely, not in the actual backtesting functionality.

@perkmeister
Copy link

Actually as we said there were 2 problems, it seems the zero length trade issue was an issue and has been fixed in the latest update (only a few days ago it seems), and the latest update has a minor bug with the adjust_trade_position being at config level not strategy level.
@xmatthias I fully intended to raise this as a formal issue with all the outputs and the like (as I said I would in the chat), I just hadn't got round to it yet, but I take your point. I should have done so sooner, my apologies.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Enhancement Enhancements to the bot. Get lower priority than bugs by default.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants