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

How to take partials using close() or sell() methods #1180

Open
danielwang730 opened this issue Oct 30, 2024 · 6 comments
Open

How to take partials using close() or sell() methods #1180

danielwang730 opened this issue Oct 30, 2024 · 6 comments

Comments

@danielwang730
Copy link

Hi,

Apologies in advance if I'm not following convention for submitting this issue, but I had a question about taking partials: specifically, is it possible to do so at an exact price specified?

For example (using made-up numbers), if I buy 20 shares of MSFT at 9:40 AM at $100/share, I want to partial (take profit) 50% if it hits exactly $102.31. Let's say at 9:41 AM the OHLC values are {O: $101, H: $104, L: $100.5, C: $102.8}, which means the $102.31 figure is met. How would I now sell 10 shares of MSFT at $102.31 exactly?

I noticed that when using SL or TP in Strategy.buy(), it would get the exact price, but I only want to take a partial, and not the whole thing. For comparison, when using TradingView's platform, their Strategy.exit() function gives options for partial amount, when to partial, etc., and it hits precisely at the specified price. Is there a way to do it here as well?

Thanks,
Daniel

@ferromariano
Copy link

ferromariano commented Nov 2, 2024

ES

La funcionalidad de configurar tu TP parcial por defecto, No existe.

Pero me parece que podes simularlo haciendo un seguimiento de la orden

Ejemplo:

EN

The functionality to configure your partial TP by default does not exist.

But I think you can simulate it by tracking the order

Example:

class MSFT102(Strategy):

    def init(self):
      ....

    def buyLimitPartialTP(self, price: float, tp_price: float, tp_partial_price: float, size: float, tp_partial_size_perce: float):
        tp_partial_size = size*tp_partial_size_perce
        tp_size         = size-tp_partial_size

        self.buy(limit=price, tp=tp_price,         size=tp_size)
        self.buy(limit=price, tp=tp_partial_price, size=tp_partial_size)

    def next(self):
        self.buyLimitPartialTP(price=100, tp_price=105, tp_partial_price=102.5, size=20, tp_partial_size_perce=0.5)

@soumenhalder
Copy link

Hey Daniel,
Just checking in—have you been able to resolve the issue? I’m encountering something similar on my end and would appreciate any updates or insights you might have!

@danielwang730
Copy link
Author

I found that using the _broker._reduce_trade method in the Broker class actually works. It's essentially overriding the buy or sell functions, and it manually places in the order you want. This is what the code looks like:

def _reduce_trade(self, trade: Trade, price: float, size: float, time_index: int):
    assert trade.size * size < 0
    assert abs(trade.size) >= abs(size)

    size_left = trade.size + size
    assert size_left * trade.size >= 0
    if not size_left:
        close_trade = trade
    else:
        # Reduce existing trade ...
        trade._replace(size=size_left)
        if trade._sl_order:
            trade._sl_order._replace(size=-trade.size)
        if trade._tp_order:
            trade._tp_order._replace(size=-trade.size)

        # ... by closing a reduced copy of it
        close_trade = trade._copy(size=-size, sl_order=None, tp_order=None)
        self.trades.append(close_trade)

    self._close_trade(close_trade, price, time_index)

And here's the link to the documentation: https://github.com/kernc/backtesting.py/blob/master/backtesting/backtesting.py

This has been working for me when I'm trying to take partials, and it also trades when you want it to. It does have its limitations of course, but I feel it more accurately simulates what might happen on a "real" trade. I've been trying to look into other packages that might do something similar, however, so I'm not sure how much longer I will be using this function. More specifically, I'm trying to look for a vectorized way to go through the data - rather than iterating through numpy arrays - to try taking full advantage of the pandas capabilities.

@soumenhalder
Copy link

Ah, I thought you meant to take a partial profit with the current price. If you partially close with some given condition, that will be a market order, not a limit order, and you would not take full advantage of price movement. The current scenario does not allow to a contingent close with a limit price and that could possibly solve the problem.

@danielwang730
Copy link
Author

Hi Soumen, I'm not sure I fully understand what you're saying, but I'll try my best to address some of your concerns:

Ah, I thought you meant to take a partial profit with the current price.

  • That's indeed what I'm trying to simulate. I may not have been fully clear about it in my previous reply, but as an example, let's say you bought in 20 shares of ABCD at $100/share at 9:40am. If your take profit condition is a 50% partial when the price hits $101, the functionality of my code will allow you to sell 10 shares of ABCD at $101 whenever it hits that mark, whether it be at 9:50am or 3:50pm. In this case, this will net you $10 in profit, and you'll still have 10 shares of ABCD

If you partially close with some given condition, that will be a market order, not a limit order,

  • You're correct in saying that partially (or fully) closing a trade will be a market order if some condition has been met. However, one of my conditions is that it has to hit a particular price. Only then should the order execute. So, while in technicality this may be a market order, by definition this would be a limit order (as a limit order executes when a specified price has been met). Thus, this functionally acts as a limit order overall.

and you would not take full advantage of price movement

  • If this is in relation to the market order vs limit order comment, hopefully my response above resolves that.
  • However, an additional question you might ask is that of slippage. To put it simply, when a long (or short) entry condition is met, I store the price that the trade should enter at. I also include some slippage to account for the realities of trading, and I can alter my price to reflect that. It's not perfect of course, and since I'm only using 1-minute data, I'll have to make some concessions in terms of accuracy; but functionally, it works.

The current scenario does not allow to a contingent close with a limit price and that could possibly solve the problem.

  • This was the sentence I wasn't sure about, but hopefully it can be resolved with my comments above.

@soumenhalder
Copy link

soumenhalder commented Nov 23, 2024

Thanks for explaining. Just one more question: are you using a modified library imported locally or overriding this function from your own Strategy class?

For my case, I modified the close function of Trade and Position to insert the limit price (and importing the modified backtesting library), but I was looking for some cleaner solution.

closefun

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants