Push an OrderUpdateEvent through the UserDataStream when activationPrice is hit for a trailing_stop_market order

Greetings, and happy festive seasons!

It would be ideal to receive an OrderUpdateEvent through/via the UserDataStream when the activationPrice for a trailing_stop_market order is hit, because then users don’t have to waste bandwidth, computing, and rate limit resources, calculating something that they could be receiving from the server. The overall quality of the API would be improved.

Currently, for trailing_stop_market orders, the sequence of events is as follows:

  1. The trailing_stop_market is placed and an event is received through the UserDataStream with status NEW
  2. The activationPrice for that trailing_stop_market is hit, and nothing happens.
  3. After some time, the reboundRate surpasses the callbackRate defined for the trailing_stop_market order. At this point, a whole bunch of things happen:
    3.1 First, the trailing_stop_market is set to EXPIRED, and an OrderUpdateEvent is received through the UserDataStream.
    3.2 Then a market order is set to buy/sell at the current price, with status NEW. An OrderUpdateEvent is received.
    3.3 The market order partially fills and eventually fills, and OrderUpdateEvents are received along the way.

For the most part, I think that works out fine. The thing that I would love to happen is, at number 2., when the activationPrice is hit, I’d love for the API to push an OrderUpdateEvent through the UserDataStream, perhaps with status ACTIVATED.

(As an optional aside, I also think it would be better if, at number 3.1, the trailing_stop_market's status was set to something like EXECUTED or TRIGGERED instead of EXPIRED, simply to differentiate it from the case where it legitimately expired because of exiting the position before the trailing_stop_market could do its thing/perform its functions. However, that’s not the main focus of this feature request.)

Ideally, and just to clarify, I think it would be perfect if the sequence of events was modified just slightly to the following instead, with the changed parts in bold:

  1. The trailing_stop_market is placed and an event is received through the UserDataStream with status NEW
  2. The activationPrice for that trailing_stop_market is hit, and an event is received through the UserDataStream with status ACTIVATED
  3. After some time, the reboundRate surpasses the callbackRate defined for the trailing_stop_market order. At this point, a whole bunch of things happen:
    3.1 First, the trailing_stop_market is set to EXECUTED, and an OrderUpdateEvent is received through the UserDataStream.
    3.2 Then a market order is set to buy/sell at the current price, with status NEW. An OrderUpdateEvent is received.
    3.3 The market order partially fills and eventually fills, and OrderUpdateEvents are received along the way.

That’s basically it for the feature request, but just to show why it would be good, here are some of the alternative workarounds for determining when the activationPrice for a trailing_stop_market order was hit:

  • I could stream the candlesticks for the market/pair that the trailing_stop_market order is operating in, using the available WebSocket stream endpoints. The issue with this is that now there’s a whole stream alive that gets hit every 250ms, and every time it gets hit it needs to do a whole bunch of calculations to try and infer whether or not the activationPrice was crossed. And this needs to happen for every position I enter. Relative to the current state of my operations, this would increase the amount of computational resources I’m consuming insanely much. In addition, I’d need to make sure that the stream is kept alive, do a whole bunch of error handling to keep things stable and robust, etcetc. More threads need to be spawned and that might not always be possible, depending on the architecture you’re using. If I was doing other stuff with the stream, it would’ve made sense, and I might in the future, but for now it’s like killing a spider with a tank.

  • I could implement a polling mechanism, and that kind of relieves some of the pull on the resources mentioned above, but now I introduce an inherent latency into the system, which isn’t ideal either. If I poll every 3min, then every 3min I could check all open orders, and for each open position, I could get a snapshot of the candlestick data, and I could just check if one of the high values in the candlestick data passed the activationPrice. I could automate this with something like a cron job or something. The issue with this is that it wastes rate limit resources, and that kind of inefficiency doesn’t scale well. In addition, now there’s always gonna potentially be a 3minute delay between when the current state of things was last updated on my side, and that’s not good.

  • Another alternative is using something like alpaca.markets, TradingView, CoinMarketCap, or perhaps some other third party application – one that hooks into the Binance data streams and that has this notification feature – and configuring it to send the notification through a WebHook or something like that. That’s still not the best, though, because the notification isn’t inherently tied to the original order in the way that it would be if I received an OrderUpdateEvent for the trailing_stop_market order that it is intended for. I’d have to match the notification with the order on my side. Maybe if the notification feature supports some kind of message, I could send the order id around and match things that way. Not an issue. The issue with this option is that now I introduce a whole different app/system as a dependency. That’s very far from ideal, because I’d have to rework things if that system falls over somehow.

  • I could split up my trailing_stop_market orders into, say, 95% trailing_stop_market and 5% take_profit_market orders, and rely on when the take_profit_market order receives OrderUpdateEvents through the UserDataStream to try and infer when the ActivationPrice for the trailing_stop_market was hit. I could link them up using a has_one relationship in my database. The issue with this is that there are a whole bunch of edge cases that might break things. One example is when a pair that I want to enter into can only be traded in integer quantities, and if I can only acquire 1 unit of that pair at the given risk, margin availability and leverage that I want to enter into, then I would not be able to place both the trailing_stop_market and the take_profit_market orders at any kind of ratio, and the whole thing would fall over.

All of that is messy, and far from ideal. The first is overkill and wasteful, the second introduces a time-delay, the third introduces a dependency, the fourth option isn’t 100% reliable and cuts into profit margins.

Overall, I think the API’s quality and value would be much improved if there was actually a general alert system and set of endpoints that dealt with these types of things. On TradingView, for example, you can setup sophisticated alerts with a bunch of different conditions, settings, etc.:

You can even make them interact with various indicators like EMA and RSI and all of that, and if we could do that over the API that would be awesome!

However, for the purposes of this feature request, I’d like to keep it scoped to just sending an OrderUpdateEvent through the UserDataStream when a trailing_stop_market order’s activationPrice is hit.

How can we go about implementing this? How long do we think it’ll take? Do you need me to help out? I’m a dev myself, and actually it would be great if we could onboard me just so that I can work on the API for my own trading purposes, and so that I can help support the growth and evolution of the API in future. Either way, I’d really love for this to happen.

Thanks!

Bump. Any news?

Any news on this? @tantialex

For the time being the team does not believe this change provides enough value to be placed in high priority. However, we are aware of the demand and may be re-visited in the future.

@tantialex how is it not valuable? What’s the reasoning?

@tantialex the activationPrice on the trailing stops is optional, right? You can send a trailing stop through and it will trigger immediately. That means that when users actually go through the trouble of explicitly specifying an activationPrice, then it must follow that it’s important to their trading strategy, right? Doesn’t it logically follow then that it would be valuable for them to be notified about when it gets hit? Doesn’t it also follow then that not notifying them is a bug?

@tantialex I have modified my entire system with a polling mechanism, where I had to start tracking each individual order I put through, modifying their state as I go. For every position that I’m in that has trailing stops that haven’t activated yet, I loop through all of those positions and actually send a request through the API for the candlestick data for that position. I had to start tracking the open_time for each trailing_stop I put through. I limit the query for the candlestick data to 99 candles, starting at the tracked open_time, and only take the 1d interval candles because I don’t really care about the actual candlestick information, and I want to minimize not only the amount of request weight resources that I’m using up, but also the actual computational resources that I’m using up in the process. I then retrieve the high values from those candles, sort them, and pick the highest one. I then make inferences for that position, which of the trailing stops have been activated, and I modify those ones’ states individually. I then also move my stop loss based on the findings and send myself notifications through my front-end.

As a client of this API, these are the things that I had to do to compensate for the incompleteness of the trailing stop activation notification in the way that I’ve detailed it to you:

  • Add state tracking to my database’s representation of a trade and a follow-up-order
  • Add a timer that does things every n seconds
  • Track every trade with some state, so that I can loop through the relevant ones every n seconds
  • Retrieve candlestick data for the positions that are relevant
  • Parse them, sort them and retrieve the highest value
  • Look through all the open trailing stops for the position, adjust their internal state manually if it’s found that the highest high is higher than the specified activation_price
  • For each one that was adjusted to be activated, send a notification through
  • Determine to which level the stop-loss now needs to be moved to, and move it
  • When all the trailing_stops have been activated, update the original order to say that we should exclude this one from the loop now
  • I still need to catch the order_update_events that are currently happening, so that I can know when they actually execute and make me money haha, I’ll probably implement that today, but essentially I need to also hook that in to the whole state tracking system too so that my polling mechanism knows to skip the ones that aren’t relevant anymore. There will be some details there that I wouldn’t have had to deal with if I was just notified about the activation_price being hit.

So yeah, I had to come up with a whole convoluted system just as a workaround, and it’s not even perfect because, now:

  • I’m using up rate limit resources that I did not need to use up before, and that I would not have had to use up if the activation_price notification was in place
  • I’m using up computational resources on a system that would not be necessary if activation_price notifications were in place
  • I’ve introduced an inherent delay into the system of up to n seconds, at any given time my local representation of what’s happening might be out of date by up to n seconds, which isn’t much of a problem but it’s a nick on the paint, yknow?

For the last issue there, you might argue, “just use websockets to stream the stuff then you’re always up to date”. The issue with that is one of tradeoffs. By using the websocket streams, I would now be using a metric firetruck-tonne of computational resources to keep track of something that a very simple order_update_event would have solved. Computational resources are not free. I’m running my system on a little laptop with a battery life, and each little computation that I need to make cuts into that battery life. If I was using a cloud computing service, each little computation would’ve cut into the computing costs.

Like, without this very simple thing, myself and a whole bunch of others need to go through a whole bunch of mission and make unnecessary tradeoffs that wouldn’t be necessary to go through or make if the order_update_event was sent through when an activation_price is hit, which is explicitly specified in the first place, and thus is important to the user of that feature.

I cannot make sense of how you can’t perceive the value here.

Hi,

Thanks for the well written request, however I failed to understand the value of this change.

  1. Are there any additional advantages for having an event sent when activationPrice is triggered apart from being able to “visualise” the state of the order better?
  2. In which scenario would a trader make a better decision knowing that their TRAILING_STOP_MARKET is “ACTIVATED” as opposed to not being aware? (Please provide scenarios and/or examples).

Just to elucidate a bit more on the previous bit - in the absence of a monkey-patch solution (or checking manually), it might theoretically take a very long time for the trailing_stop_market to actually execute (i.e. the rebound rate passes the callback rate). Right now there’s no easy feedback to know that it’s safe to proceed with other trades in the interrim :nerd_face:

From that perspective, it might even be categorized as a bug, tbh

Hi,

  1. Being able to “visualize” the state of the order better is already valuable in and of itself. Having more, higher quality information about the state of affairs makes it easier to make better-informed decisions. When you implemented the websocket endpoint for streaming candlestick data, did you ask your clientbase what they’re gonna do with the information or did you just provide it, knowing that different people will use their own creativity in different ways in applying that information?
  2. In a nutshell, when the trailing_stop_market is ACTIVATED then that portion of the trade is not at risk anymore. When traders are operating under strict risk management protocols, that means they can then proceed to enter into additional trades, since the risk exposure has lessened. The ACTIVATED state is a clear signal/indication that risk exposure has decreased.

I can provide what I’m going to be using it for in my own strategy, but not on a public forum :slight_smile:

When you implemented the websocket endpoint for streaming candlestick data, did you ask your clientbase what they’re gonna do with the information or did you just provide it, knowing that different people will use their own creativity in different ways in applying that information?

It is important to understand that any additions to a public interface will affect all users, therefore, even a slight addition such as RSI will affect all connected clients, even the ones who do not require such an addition. With that said, the fundamental properties are provided via the stream for users to perform their own calculations with as little latency as possible.

When traders are operating under strict risk management protocols, that means they can then proceed to enter into additional trades, since the risk exposure has lessened. The ACTIVATED state is a clear signal/indication that risk exposure has decreased.

While this is true, traders should gain no advantage receiving an event on ACTIVATION_PRICE triggering as risk exposure decisions should be taken against real-time changes of the market, thus implying the trader already has an open connection with a websocket market stream allowing them to evaluate if the order hit the activation price or not.

Right now there’s no easy feedback to know that it’s safe to proceed with other trades in the interrim :nerd_face:

In theory, a trailing_stop_market order’s risk does not change if the activation price has been hit or not, assuming the same market price is applied to both scenarios. As mentioned previously, this type of risk assessment should be done by listening directly to market changes and not order changes.


With all that said, I will push this feedback to the respective team for awareness sake and so that they can evaluate the importance and value of such a change.

traders should gain no advantage receiving an event on ACTIVATION_PRICE triggering as risk exposure decisions should be taken against real-time changes of the market, thus implying the trader already has an open connection with a websocket market stream allowing them to evaluate if the order hit the activation price or not.

thus implying the trader already has an open connection with a websocket market stream

Not at all. I don’t use the websocket market streams. I rely fully on the OrderUpdateEvents getting passed through the UserDataStream.

even a slight addition such as RSI will affect all connected clients

Only if you push it through an existing endpoint, if you push it through a new endpoint then nobody’s touching it and so it won’t affect anyone. Pushing this event through the stream won’t affect anyone that isn’t explicitly listening for that particular event, but it definitely will bring clarity to the way that type of order works, and also to the state of things happening in real-time.

In theory, a trailing_stop_market order’s risk does not change if the activation price has been hit or not,

The trailing_stop_market's risk does not change, no, but the position taken for that particular trailing_stop_market does. If you’re running, for example, a long position on something with a stop-loss at the bottom and a trailing-stop at the top, then the position is at risk up until the moment the price hits activationPrice. The moment that threshold is crossed, the position is no longer at risk, but until it is crossed, the position is still at risk.

While this is true, traders should gain no advantage receiving an event on ACTIVATION_PRICE triggering

And yet here I am, trading the markets, in a position where I will gain advantage from receiving an event on ACTIVATION_PRICE triggering.

As mentioned previously, this type of risk assessment should be done by listening directly to market changes and not order changes.

There’s a cognitive bias going on here. Your own personal framework/lens/perspective/model of how the markets ought to be traded, is impeding your ability to perceive the value that the API’s clientbase will derive from this feature. A million traders will trade the markets in a million different ways. As one of those million traders, I’m asking for a direct improvement that shouldn’t be a lot of work and that will also provide a lot of general clarity to how the order works, and also clarity into what the order’s state of affairs is - something that will improve the quality of the UserDataStream. It’ll make the UserDataStream better.

The existence of an event being passed through the UserDataStream when activationPrice gets hit on a trailing_stop_market order, will make this world a better place, at least for me, and I’m sure for others too :smiley: