ctubio / Krypto-trading-bot

Self-hosted crypto trading bot (automated high frequency market making) written in C++
https://127.0.0.1:3000
Other
3.32k stars 819 forks source link

Safeties #835

Open ctubio opened 7 years ago

ctubio commented 7 years ago

@Camille92 said at #28:

The goal of this safety is to be protected by sudden rise or drops in the price. It works with a simple formula: If x% drop (or rise) in y minutes : market sell (or buy) your position + change TBP to 0 (or 1).

Example: If I set the limit to be 2% in 5 minutes if the price moves up by those number, I market buy to enjoy the ride.

Target base position has to be changed when the safety is triggered so that tribeca doesn't start to sell and/or activate APR right after buying. The difficult part is to find a trigger for when to start to reuse normal APR instead of the "safety" one. I have two ideas for that the first one is to switch back to normal when EWMA 100 starts ro rise (or go down). The second one is to use a timer counting to 10 or 20 minutes.

Camille92 commented 7 years ago

capture d ecran 2017-04-13 a 12 42 08

Example of a case where safeties are useful. In the above graph, the EWMA are still very close together so tribeca's target base position is a good mix of fiat and btc. With safety, we can expect tribeca to drop the btc in the middle of the fall and not after it :)

Camille92 commented 7 years ago

The difficult part is to find a trigger for when to start to reuse normal APR instead of the "safety" one. I have two ideas for that the first one is to switch back to normal when EWMA 100 starts ro rise (or go down). The second one is to use a timer counting to 10 or 20 minutes.

After having a look at the logs and thought about it, a good solution is to reuse the EWMA calculation once fair value is recalculated (every 20 minute according to current settings). -> https://github.com/ctubio/tribeca/blob/master/src/server/position-management.ts#L32

If we take the example of the above fast crash we can see that tribeca successfully adapted a good target for the situation at the first update of fair value after the drop that happened at 6am.

{"name":"rfv","hostname":"6a42d0df9c43","pid":14,"level":30,"msg":"recalculated regular fair value, short: 1214.31 long: 1214.66 target: -0.15 currentFv: 1211.28","time":"2017-04-13T05:48:05.717Z","v":0}
{"name":"rfv","hostname":"6a42d0df9c43","pid":14,"level":30,"msg":"recalculated regular fair value, short: 1207.28 long: 1211.11 target: -1 currentFv: 1177.32","time":"2017-04-13T06:08:05.718Z","v":0}

Logically we can say that safety should be turned off after fair value is recalculated!

Camille92 commented 7 years ago

Some readings to help!

The original idea comes from Haasonline and I find it quite clever so here it is how they describe it. General view of safeties: https://wiki.haasonline.com/Safeties

The most interesting one: https://wiki.haasonline.com/Dynamic_Drop_Loss

ariejan commented 7 years ago

+1 to this. I've been trading/testing with tribeca for a week or so now. This safeties feature would be awesome. Steep rises and falls complete mess with my trading settings. However, with safeties, I could ride out steep changes more profitable, and resume trading when things stabilize.

Camille92 commented 7 years ago

Hello all,

After some thinking, I'm coming with what I think is an easy and efficient implementation for that. @ctubio I think this can help you automatize buying even in a downtrend as you were telling me yesterday and @beegmon tell me what you think about it.

The idea here is to define a "new" strategy within Tribeca that would be activated only under certain conditions. I think that "Safety buy" and "Safety Sell" are logical names for those strategies.

The implementation:

1) Determining what's a quick trend:

This is done by calculating the SMA 3minutes. This is done by calculating the average of FV for the last 3 minutes. (with 1 data for each minute) Then we compare this SMA 3 to the SMA 3 of X past minutes (chosen by the user). If SMA 3(new) is greater/lower than Y% (chosen by user) then the bot changes to "safety buy" or "safety sell mode"

Note: We take SMA 3 instead of just FV to be protected in case of a single big order shot the price high/low for a few seconds.

Formula: If ((sma3.latest*100 / sma3.-X) - 100) > Y activate mode "safety buy" else -> nothing

If ((sma3.latest*100 / sma3.-X) - 100) < -Y activate mode "safety sell" else -> nothing

2) Safety buy and safety sell mode:

Those modes should activate a particular set of actions.

a. Changing Target Position : If Safety buy is true -> Target Position = 1 If Safety sell is true -> Target Position = -1

Note: Target Position (TB) is what determines TBP in https://github.com/ctubio/tribeca/blob/master/src/server/position-management.ts and 1 means full crypto -1 means 0 cryptos (TBP = 0).

b. Optionally allow to change pdiv to 0

Add an option for pdiv to be equal to 0 in case safety mode is activated, so you don't have money left behing.

c. Optionally becoming a taker on the market for faster repositioning

This option can be quite dangerous if badly used, but can also be miraculous when properly implemented. That's why I'm coming with 3 ideas for being a taker.

Option 1 Market: Simple market order of the size of what's left in the account. Very efficient be can be risky and don't give the best prices. Now rejoining #100 Option 2 Sniper: Limit order of the size and price of best.bid / best.ask repeated until TPB + pdiv is met. Option 3 Sniper + STDEV: Same as Option 2, but only if best.bid / best.ask is within FV +/- STDEV.

UPDATE: Limit order should be at the maximum size possible and at best.bid or best.ask price, because we can be lucky and someone can match us + we have nothing to lose.

3) Quitting Safety mode:

Safety mode should be exited when the trend is over and Tribeca must then come back to the TB calculated by the EWMABasic or manual option.

A good way to exit the mode is to reuse the SMA3 and check if the last SMA3 is above or under the previous the SMA of the past Z minutes defined by the user. It can be also interesting to put a timer that determines how long safety should last at minimum.

Formula: If SMA3(latest) < SMA3(-Z) && timer over Quit Safety buy Mode

If SMA3(latest) > SMA3(-Z) && timer over Quit Safety sell Mode

Recap: To implement the safety we need: to calculate the SMA3 and play with it. Allow the user to chose for X = time difference and Y = % difference between the two SMA and Z the time difference to quit Safety mode and a timer for quicking safety mode. Create Safety buy and safety sell mode that change TBP to 100 or 0 Define the way to send orders according to the Taker strategies

If we have the settings of X = 5 minutes, Y = 2% and Z = 2 minutes and timer 10mn. If means that if the price (the SMA) moves by more than 2% in 5 minutes the safety mode will be activated. It will be on for at least 10 mn and until the SMA actual is over the SMA of 3 minutes ago in case of safety sell and vice versa in case of safety buy.

I hope it makes more sense for you and it's more clear what I try to achieve here.

Peace!

Camille92 commented 7 years ago

Here is an approximate image of what it would look like in BTC/USD with the settings named above and the bumpy morning. capture d ecran 2017-05-27 a 15 21 58

Of course, settings needs to be optimized. But you can only do that by testing it!

beegmon commented 7 years ago

I assuming the places where it says "stop" are where you have triebca stop trading completely?

Camille92 commented 7 years ago

Nope it's when the safety mode stops and Tribeca goes back in its normal mode.

This is not actually what my Tribeca did, it's an example on how Tribeca would have performed with the safeties as described above.

beegmon commented 7 years ago

Ah, that makes more sense. I need more coffee.

I was in the process of typing up something nearly identical to this. The only difference was I was using EMA instead of SMA for FV because I wanted to weight more recent price changes.

Secondly, I was going to track the aggregate value of the BTC I currently held as an extra data point to make safety sell decison. That is to say, if I take an EMA of all the prices in which I bought the BTC I currently hold at, and if the FV EMA is under say 10% (user settable) of my held BTC value, then market sell my BTC holdings.

However, I think your approach is simpler/easier to implement and cover 99% of what I was trying to cover in my thoughts. And I love the fact that I can adjust how agressive it is by changing the time window for each FV in the SMA, the amount the FV SMA must be under/over, and the confirmation of that SMA change. Its nearly exactly what I was thinking about doing besides the EMA of the FV and EMA of the "value" of the BTC held.

Camille92 commented 7 years ago

Happy to hear that.

The good reason to use sma instead of sma is that we use them to have a correct and smoother estimation of the price at a time t. If we use ema 3 then it would not be smooth as well.

Ps: I don't recommend you to implement your strategy taking into account the price of the btc you bought, because here we try to guess future price and past data doesn't matter much.

In other words, even if you're 10% down it doesn't matter, what's important is to know if in the next minutes the price is going to go up or down.

beegmon commented 7 years ago

SMA makes sense since as you said, it is smoother.

I also see your point about not wanting to use the BTC value when considering future FV changes. It is certainly simpler, and assumes that the BTC you currently hold was bought at the current FV, which very likely isn't the case.

By making such an assumption you also attempt to maximally protect any gains you have at the moment (when issuing a market sell for example), or gaining more BTC position quickly (when market buying). I think that is a perfectly fine approach. I was going for something that was more fine-tunable and attempted to take into account coin age/price bought to better determine if a coin should be market sold, or if the predicted FV change is enough to warrant a market buy.

However, after a weekend of testing it and getting a better idea of what the average coin retention time is in Tribeca, I can safely say that in general Tribeca doesn't hold any one specific coin long enough to benefit from knowing the coins original price when comparing to the current FV or future potential shifts in FV. So its moot.

For a longer holding bot, one that trades far less and attempts to take advantage of the more "macro" picture of the market I can see it as a benefit. But Triebca works on small time scales, and trades very often. In that case, it doesn't hold on to coins that long, so looking at a maco picture of assets vs current/future price doesn't really benefit much, and just adds complication.

ctubio commented 7 years ago

i think i know what is SMA20, sooo.. SMA3 is the same but just with a sequence of the last 3 recorded periods?

Camille92 commented 7 years ago

@beegmon I'm totally agreeing with you, it can be very interesting to keep a record on when you bought when you have a technical analysis bot that only trades a few time a week/day.

But for Tribeca the market making side of the bot makes it less relevant.

@ctubio Yes exactly, the SMA3 is the moving average of the 3 last recorded period, knowing that a period is one minute. The convention is to name the indicator and number representing the number of periods it's looking at, as well as what the period is worth. Ie: MACD (12,26,9), EWMA (100), STO(14) etc 😄

ctubio commented 7 years ago

i think the triger for "1) Determining what's a quick trend:" can be the current profit %, instead of SMA3 of FV, no? seems redundant to have 2 ways to define a "quick trend"; based on when the current profit reaches a customized %, we can start/top the buy/sell safety, don't you agree?

Camille92 commented 7 years ago

In theory yes it could work that way,

However, you have a few issues with that: 1) You would need to set your profit to a very low value to be relevant (3, 5 or 10mn).

2) Your profit can be different than the evolution of the market: If you are out of btc and btc goes up, your profit stays the same (0) while btc is going up so you don't trigger the safety.

3) For people in multi-market like me, current profit is definitely not a relevant tool -> because money is poured or taken off from other markets while the price is not evolving

I hope it makes sense to you :)

ctubio commented 7 years ago

ok definitely we are talking about two diff profit messures here, ok ty'¡'

Camille92 commented 7 years ago

capture d ecran 2017-06-06 a 20 07 28 I made an image so hopefully, it's more clear.

Here we work in pairs. Each minute we compare the current price (SMA3) to the price of SMA3 X minutes before.

So let's look at the chart here in the settings X = 6 minutes.

So when minute A' arrives we look at the price at minute A and see how much the price evolved by doing: A' * 100 / A

Then a minute B' we do the same by comparing with B situated 6 minutes before.

And we keep going like that for each new minute.

If at some point the percentage obtained by the calculation is bigger than the trigger, then we activate the safety mode!

zachaller commented 7 years ago

Ok I tried to follow this the best I could I have also been thinking about a feature that would be nice that seems somewhat related to this. What i would kind of like to be able to have tribeca do is automatically switch the pings to either BidSide or AskSide based on idea's from this ticket but instead of adjusting tbp switch the ping side so I can still use a manual tbp. Do you think this would be a worthwhile addition or not?

Camille92 commented 7 years ago

Hello everyone,

As I think that's a great innovation that will benefit everyone, I put a 0.05Btc (or €100 equivalent if the price continues to drop) for this feature to be implemented :). Other traders / non-coders that think that it is needed don't hesitate to add to this virtual pot so it makes it more attractive to implement :).

@zachaller I don't really understand what you mean here. This feature will override TBP "normal calculation" (which goal is to give you a trend) to have a way quicker reaction to market evolution.

zachaller commented 7 years ago

@Camille92 so i generally do not like the idea of dynamically adjusting TBP because I want to hold onto most of my crypto coin for the long run as well as I have a pretty large account that I do not want to be sold out of by the bot. So instead adjusting TBP dynamically I like to keep it set to manual mode with a set pdiv but then be able to change the ping at to either favor bid side or ask side based on what the market is doing. So if the market is in a down trend pings will be set to the ask side which then seems to let the bot sell out most the coins until it hits TBP-pdiv and when the market is trending up I want to switch pings to bid side as that seem to make the bot buy back most most of the my pdiv setting. Dose that help clarify and maybe I am missing the point a lot of this market stuff is pretty new to me.

ctubio commented 7 years ago

@zachaller about your suggesiton at https://github.com/ctubio/tribeca/issues/32#issuecomment-307486124, im not sure that i understand it :P do you think if you still want it that you can open a new issue for it and explain it niiiiicely? (or is highly related to this issue? [anyway i didnt understood very well your comment so i will need more details somewhere anyway if you still want it, thanks'0¡])

what you explain at https://github.com/ctubio/tribeca/issues/32#issuecomment-311460458, is not the current behaviour of TBP? (i dont see the diff sorry)

Camille92 commented 7 years ago

@zachaller Hey I think I understand what you mean now, but indeed as @ctubio said it's a different issue (don't hesitate to open a new issue on the new GitHub page).

So it can not be done with the current state of the bot because if the market is going is going up then you will find more market buyers and if it's going down more market sellers so you will always be at the lower limit of pdiv on an upmarket and higher limit on a downtrend market.

In order to solve your issue, I think what we need would be to still have dynamically adjusting TBP BUT with a manually set upper and lower limit.

In other words, you will still have tbp moving according to your ewma settings but you can, for instance, tells the bot to never have less than 50% crypto and never more than 80%. So TBP will oscillate between those two numbers according to market conditions.

What do you think?

PS: If you have a lot of crypto (but not too much, less than 100k) you can choose longer ewma periods like 500 - 1000 to only ride big movements.

Camille92 commented 7 years ago

It can be done quite easily here https://github.com/ctubio/Krypto-trading-bot/blob/master/src/server/position-management.ts#L97 with something looking like:

if (newTargetPosition > UPLIMIT) newTargetPosition = UPLIMIT;
if (newTargetPosition < LOWLIMIT) newTargetPosition = LOWLIMIT;

With UPLIMIT and LOWLIMIT being between -1 and 1.

ctubio commented 7 years ago

@Camille92 but the normal user (like me) is not able to accurately work with 1 and -1 to set an amount; better maybe to work with wallet amount units (btc or whatever [or % if % is enabled]), and use this HIGH and LOW amounts customized by the user as limit to avoid drain passing this limits; in other words, instead of allow TBP to go in between 0% to 100%, now we would like to customize it so it can go in between for example only 30% and 90% (or wallet units if % is disabled)

i am right? (if so, i will shutup and open a new issue for this, cos i think is not related to #32) if so, the mod i think is at https://github.com/ctubio/Krypto-trading-bot/blob/master/src/server/quoting-engine.ts#L151 (we need a new condition to also stop but in other situation not only because pDiv)

Camille92 commented 7 years ago

Yep exactly the same idea, it's just that target position works internally with value based between -1 and 1.

We can easily translate that in % in the web UI by doing:

if (newTargetPosition > (UPLIMIT/50)-1 newTargetPosition = (UPLIMIT/50)-1;
if (newTargetPosition < (LOWLIMIT/50)-1 newTargetPosition = (LOWLIMIT/50)-1;

With LOWLIMIT and UPLIMIT being a number between 0 and 100.

Working with raw value:

if (newTargetPosition > (2*UPLIMIT/TOTALPOSITION)-1 newTargetPosition 
= (2*UPLIMIT/TOTALPOSITION)-1;
if (newTargetPosition < (2*LOWLIMIT/TOTALPOSITION)-1 newTargetPosition = (2*LOWLIMIT/TOTALPOSITION)-1;
Camille92 commented 7 years ago

I think this was closed by mistake because https://github.com/ctubio/Krypto-trading-bot/issues/32 is 32 as well :)

spudstr commented 7 years ago

I've changed the exit logic on this.. this is what it looks like.

SMA3_current < SMA3-X periods AND ( ( SMA3-X periods(timestamp) + (safetystart_timestamp+(safetimeover_duration * 60000) )

SafetyStartTimestamp ) AND current safety mode = sell in this instance

If these conditions are true... we exit safety sell.. for a buy safety.. simply reverse the > with < on the firs statement.

spudstr commented 7 years ago

updated the logic a bit.. think thi works a bit better.

SMA3_current < SMA3-X periods AND { timediff SMA3-X, safetimestarted > ( safetimeDuration(in minutes) * 60) } AND safemode = buy in this example

this should exit safe buy once SMA3-X periods is more than then safetimeduration, in the event that SMA3 keeps moving

ctubio commented 6 years ago

i think this was done recently after the adding the ewma up/down trend safety