gruelbox/orko

Laddered OCO order with multiple entries/take profits

Zkffkah opened this issue · 13 comments

Hello, can we support all in one oco order like 3commas and other platform provide.
https://support.3commas.io/hc/en-us/sections/360000044853-Smart-Trade

For example,
I can set all these things in one order.
A. Buy Order with multiple price and quantity.
first buy at 220 sats with 0.1 btc, second buy at 210 sats with 0.2 btc
B. Stop loss order
Stoploss at 180 sats
C. Multiple sell target
sell 30% at 300 sats, sell 50% at 350 sats, sell 20% at 390 sats

We can add a new type for this or we can use the script function to do this?

I've thought about this before - a combination of a ladder order and OCO. FYI there's also #152 which I think is pretty important.

Yes, you could definitely do it with a script easily if you're happy with a fixed number of "ladder" prices (e.g. buy 1, buy 2, buy 3). However, you don't actually NEED ia new order type to do what you want. You could just use the existing OCO feature to place multiple "soft" buys and sells at different prices. You are allowed to use OCO with only one buy or only one sell (just only fill in the "below" section or the "above" section. It's a little bit weird and it's a bit bit more work when setting up a trade, but it works. It's what I do.

The big thing you don't get with that approach is "reduce only" behaviour on the stops/take profits, which can definitely get you into trouble if you're not careful!

Ok, I got your idea of using existing OCO to achieve this. So we place multiple oco here
A. OCO for a stop loss
B. multiple OCO for a laddered buy
C. multiple OCO for multi target
But how do you control the size here? What if the buy just partial filled here? The sell order or stoploss order may not get executed here? Is this what your "reduce only" means? It seems we can't modify the order once we create it, so need to recreate the oco sell and stop loss for the partial filled here?

Regarding the script implementation, it seems we can only create limit order in js and we can't get the status of the order we create. So the same partial filled problem, the stop loss and take profit order might not executed I think?

Yes, there's no way (currently) of modifying orders.

Any "soft" order (a stop or take-profit using OCO) should automatically reduce in size to match the available balance when it places the limit order on the exchange. So, if you have:

  • 0 BTC balance
  • 1 BTC limit buy on exchange at 6000 USD
  • 2 BTC limit buy on exchange at 5500 USD
  • 3 BTC OCO sell triggering below 4999 USD with limit price of 4800 USD (stop)
  • 1.5 BTC OCO sell triggering above 9000 USD with limit price of 8800 USD (take profit)
  • 1.5 BTC OCO sell triggering above 10000 USD with limit price of 9800 USD (take profit)

Then if the price dips to 5700, then spikes immediately up to 9500, then down to 5400 and then up to 11000, what will happen is this:

  1. Orko sends you an alert when placing the three OCO orders that the balance is insufficient and the order sizes will be reduced
  2. Limit order fills at 6000 (balance is now 1 BTC)
  3. OCO triggers at 9000
  4. Orko recalculates the order size down to 1 BTC to match available balance
  5. Orko sends you an alert saying it has done this.
  6. Orko places a limit order at 8800 USD for 1 BTC.
  7. Order fills (balance is now 0 BTC and you are a happy camper)
  8. Limit order fills at 5500 (balance is now 2 BTC)
  9. OCO triggers at 10000
  10. Orko sells 1.5 BTC at 9800 (balance is now 0.5 BTC but you expected it to be 0 BTC)

I hope that gives you an example of the sort of thing that might happen. Another example is what could happen if the price just immediately rose to 11000 without hitting your limit orders and you already had some BTC held - it would sell that BTC without having bought any extra,

With a proper, integrated ladder/OCO order, we could automatically cancel/adjust the linked orders to make sure they produce a consistent result and don't affect balances outside that "block".

OK - one other point: see #344 - there is a bug with the calculation of the trade amounts on some exchanges which can cause the take profit to fail, depending on whether the exchange takes the fees from the purchased asset or in addition to the purchased asset. So, the initial limit order for 1BTC might leave you with 0.999 BTC when 0.1% fees are subtracted on some exchanges, but on other exchanges, it will leave you with 0.1 BTC but take the additional 0,1% from your USD balance. That does need fixing urgently.

I know this is definitely not a problem on Binance if you use BNB for fees but I'm not 100% certain about the others, so I suggest testing it before relying on it until I fix that bug!

Sorry this is all a bit complicated! I'm working on this in my spare time so things can take a while.

Thanks for the detail response, I got what you mean now. So still a problem here, if we have three buy oco but only one get filled, if we want to set three target to sell, then we may sell all the filled asset in the first oco sell order. Maybe we could add someway to get the order status in the js so that we can check it in the script? And if I implement this in a script, how can we show the status in the ui, it seems no way to pass out data currently?

Oh, #144 looks like you already notice the script problem.

I think another way to do this is on the user side, add a interface including dynamic number of rows to place multiple oco order in one click submit.

I've been thinking about this regarding the "full" solution.

What do we want to happen if only some of the entry orders hit and then we start hitting the laddered take-profits? We can't fill all of the TPs (we didn't buy enough) so:

Should we cancel the first TPs we are going to hit, or the last? Or should this be an option?

That is: if I have buys at 120, 110 and 100 and sells at 180, 190 and 200, all for 0.1 BTC, and my 120 and 110 buys get filled, should I cancel the sell at 180 or 200?

In my opinion, we should sell at percentage of each target. Like if we set sell 30%(0.09btc) at 180, 30% (0.09btc)at 190, 40%(0.12btc) at 200, but only 0.2 btc of 0.3 btc filled. So now, we sell 30%(0.06btc) at 180, 30% at 190, 40% at 200.

What do we want to happen if only some of the entry orders hit and then we start hitting the laddered take-profits? We can't fill all of the TPs (we didn't buy enough) so:

Should we cancel the first TPs we are going to hit, or the last? Or should this be an option?

I think this would depend on your trading strategy.

If you are trading a trend, I think cancelling TP orders should be an option if early limit orders start getting hit, but you werent filled completely.

However, there are times where you want to keep the old orders in, for example, if the price is stuck in a range and your buy/sell orders are staggered in an area of outer standard deviations for those ranges.

Trailing stops should also always be an option to seal in profit, which should also give the user the option to allow the cancellation of all lower bids (or upper asks) still on the book if the trailing stop gets hit.

Now, how do we decide where the TP orders will be? Its always a nuisance to fill in everything manually...this is where ability to calculate simple TA (EMAs and Standard Deviations) would come in super handy.

Agreed. There are loads of good things we could do with candlestick data and a TA library like ta4j.

Some exchanges publish candlestick data, but not all. The first thing would be to try and create a standard API for candlestick data in XChange. That would provide an exchange-independent means of calculating stuff like MAs, and those can then be used in scripts as well as calculating ladders and even driving a fully-integrated TradingView chart (so you can show and adjust trades on the chart and save chart settings...)

I think lowwer also has a good point. Automatically adjusting TP level QTY by the total % actually filled is a good idea.