[Passed] Motion to regulate spread values for liquidity operations

Please see if this is alright. I’m putting it into the original post for now.

=##=##=##=##=##=## Motion hash starts with this line ##=##=##=##=##=##=
For all liquidity operations that are paid for with custodian grants, operators shall ensure liquidity providers are not discouraged to provide liquidity up to a specified spread limit, which we define as the guaranteed tolerance.

Under a guaranteed tolerance of x%, liquidity providers shall be compensated at a uniform rate for bid orders made at x% below the target peg or above, and for ask orders made at x% above the target peg or below, where the target peg is defined as 1NBT = 1USD.

Liquidity providers shall be informed with the guaranteed tolerance, and given convenient options to provide liquidity at the maximum permitted spread within the guaranteed tolerance, such as by having such option chosen by default.

This motion also imposes that the minimum guaranteed tolerance of liquidity operations between NBT and other cryptocurrencies is 0.5% plus the exchange fee rate. For example, if the exchange fee is 0.2%, then the operator shall ensure that the guaranteed tolerance is at least 0.7%, i.e. all liquidity providers who make orders at up to 0.7% spread on either side are compensated at equal rates.
=##=##=##=##=##=## Motion hash ends with this line ##=##=##=##=##=##=

But the actual operating spread, i.e. the ‘spread’ parameter as defined in trading.py, will end up being %0.5. I don’t want to belabor the point, I just want you to be aware what this means and that it’s different than what you made mention of. For example, under this motion, a liquidity provider will end up placing orders for 0.995 NBT and 1.005 NBT. If you wanted %0.5 after fees, you would want them to place orders at 0.993 and 1.007. To accomplish this, we need to credit orders at 0.991 and 1.009 because the effective price feed deviates from 1 NBT by approximately %0.2.

Your motion is fine, but honestly the only thing it will change is that pool operators will be more aware of their defaults. All current pools satisfy the limits imposed by this grant as is. A tolerance that would allow %0.5 profit above and beyond exchange fees would be more like %0.9 tolerance, and would require all crypto pools to change their server parameters.

I see your point. In the current draft it is for pool operators to make sure 0.7% spreads are actually paid for, even if it means there would be side effects e.g. the practical server tolerance has to be made higher than 0.7%.

I will try to make this more nuanced, but I also want to give it a more general tone. Perhaps we can talk about best effort, and let grant proposals state some of the side-effects if it affects the actual spread.

I am almost guilty for asking pool operators to do more work spelling out details like this, but I also feel that spreads are important enough an aspect that we should regulate.


The issue is that it is not the server’s job to make sure the client is keeping up on the price feed. If an operator uses %0.7 tolerance, then indeed all orders that are %0.7 away from the server’s price feed will be credited. However, in reality this means that the client must operate at a smaller spread if they want to be credited 100% of the time. We could definitely phrase it in a ‘best effort’ way, but then this isn’t exactly a formal statement of minimums.

If you want a formal statement that is also fairly general, pool operators can very straight forwardly comply with:
No TLLP grant shall be provided for a crypto pool operating at a tolerance of less than %0.7 plus the exchange fee.

I just think we should be clear about what we’re asking pool operators to do here, especially with regards to a static number like tolerance.

Edit: I guess what I’m saying is that currently, with our %0.2, we are effectively operating with a %0.4 tolerance. If you want to increase our spread by %0.5, we need to increase the tolerance by %0.5, so we need a %0.9 tolerance.

The talk of tolerance is mostly unnecessary except from the shareholder perspective, I’m sorry I spoke of it so much. I hope this isn’t too forward, I was just having trouble explaining it completely:

=##=##=##=##=##=## Motion hash starts with this line ##=##=##=##=##=##=
For all liquidity operations that are paid for with custodian grants, operators shall ensure liquidity providers are not discouraged to provide liquidity up to a specified minimum spread, which we define as the guaranteed spread.

Liquidity providers shall inform shareholders of the corresponding tolerance and give participants convenient options to provide liquidity at optimized values for spread and deviation, such as by having such options chosen by default.

This motion also imposes that the minimum guaranteed spread of liquidity operations between NBT and other cryptocurrencies is 0.5% plus the exchange fee rate. For example, if the exchange fee is 0.2%, then the operator shall ensure that the guaranteed spread is at least 0.7%.
=##=##=##=##=##=## Motion hash ends with this line ##=##=##=##=##=##=

This is a very interesting discussion and one that I want to participate since I have been dealing with those walls full time for one year now.

TL;DR; I agree we should agree on a min-max spread range and force custodians to use that.

Whatever the outcome of this motion will be, I will reflect it in the default parameter used locally by nubot and on the push streaming service.

I think that great part of this discussion is not new and there is some “reinvent the wheel going on” in this thread.

I am not sure we ever had a written contract/rule/motion anywhere obliging custodians to use a specific spread. Its about time we find an agreement on this and I am glad you came up with a proposition. So far spread has always been exposed as configuration parameter from 0.1.4 in NuBot ( I am not sure how it works in the TLLP) and several times custodian changed it to see market reactions. The default spread in nubot is 0.4%, aka 0.2% per side (plus the exchange TX fee, which changes depending on the exchange) .

While I am well aware of the spread problem, I believe the solution cannot be imposing an arbitrary large spread alone. Rather it should be a dynamic market-aware spread (planned in a few iterations of nubot) combined with liquidity distributed around a central price rather than single walls.

That’s not actually true. We are now testing now 0.3.1 and 0.3.2 will come shortly after, most of the work is already there. Anyway, regardless the fact that we have the parametric order book in place, this does not affect your motion about imposing a boundary bid/ask spread. So in this sense this motion is very welcome.

Re OP : your reasoning is correct when you say that we have high cost of maintenance. I find it a bit flawed when you make a comparison with the orderbook of LTC at a random instant of time taking only the top bid/ask. One of the points of NuBits is providing liquidity in a way other coins cannot provide, resulting in outstanding market velocity. Please see some interventions here and here where @JordanLee calls for nubits as an “intermediary coin” thanks to its liquidity operation, along with all my opposition and final outcome. So really, the LTC comparison doesn’t help much the discussion imho.

We deal with three kinds of pairs, grouped by volatility level
NBT/USD (0 volatility)
NBT/FIAT (little volatility)
NBT/CRYPTO (high volatility)
Please specify boundaries for each specific case.

When you say guaranteed tolerance do you mean the bid/spread ask? Or are you saying that sell orders should be placed at the crypto equivalent of 1$+0.07$ and buys at 1$-0.07$ ? In the latter case, its more an offset expressed in $ from target price rather than the traditional bid/ask spread of orderbooks. Wording is important in motions, please edit.

How do you measure the bid/ask spread in percentage btw? In different codes/docs I’ve found at least three different ways to compute the spread and the result is different.
let bestbid be the price of the highest bid and bestask the price of the lowest ask.

 spread1= |(bestbid/bestask) -1| * 100
 spread2= |(bestask/bestbid) -1| * 100
 spread3= (|bestask-bestbid|) / (((bestask+bestbid)/2)/100)

Beside some adjustment to the text of the motion, I think the rest looks good.

Also, please take into account that while I think that setting gross boundaries for the spread is a good idea, the next step is to make the spread dynamic, aka, market-aware.

Comments on other replies

:point_up_2: very correct

So @masterOfDisaster is also proposing a maximum spread for compensation. Is this clear in your motion?

c) in the early stage of a product custodian and the network had to pay a price to comply with the “always 1$” promise rather than “more or less 1$”.

Also here I am getting a bit lost. I am not even sure who is developing what. We had long discussion on price feed/averages/tolerances/sync across exchanges, custodians, etc. Hours have been spent in design and development in this regard. Last time I spoke with creon I told him that we were about to roll out a “push” service that suggests prices to bot (and spreads soon). It is being tested as I type actually, and I strongly believe that TTLP clients should consume this service and be advised on prices (and spreads later). Did someone else took over development of pools? Whoever is working on it, can please make sure that we don’t make (wrong) things twice? This is also at the expense of shareholders.


Ok, that’s really cool. That’s different from the current setup where the client picks the price to put the order up at and I applaud it.

As far as the people running %0.2 spreads being ignorant, I just meant from the perspective of TLLP, where most pools can actually be run with >%0.5 on either side without penalty. If a person is offered free money and doesn’t take it, either they are ignorant of the offer or they are feeling generous. Running with a low spread intentionally for the good of the network at the cost of your own finances is considered generous in my opinion.

I propose a global minimum spread of %0.5 to either side (%1 standard trading spread) for all liquidity operations on currencies that are deemed ‘high volatility’. So if BTC were worth exactly $1, we would do best efforts to compensate sell orders at $1.05 and below and buy orders at $0.995 and above. It’s a little convoluted, because the minimum allows for pools which compensate sell orders well above market price, but I believe such pools will never get a grant proposal passed. This is meant to be a minimum guideline for pool operators, and a requirement that they state what their actual compensated spread is, such that shareholders can use it as a voting parameter.

Maximum global spread compensated should be something like %5, I think, to correlate with legacy.

There is a misconception here, and it is very important to clarify it.

Even with very sophisticated algorithms, wide spreads, small walls, custodians on crypto pairs are at high risk of losses in term of USD. Custodians will generally be on the wrong side of trades. They will buy NuBits when BTC price is raising , because traders want to enter BTC and leave NBT. Viceversa, traders will buy NBT from custodians when they “feel” BTC price is going down, leaving custodians with a devaluing asset.
This is a fact. The spread can do nothing against it. A 1% spread protects us from instantaneus arbitrage, mispricing , hft bots, bugs. A 1% spread will not protect us from BTC swings that are generally in the order of 5-10% , daily.

I hear you, that is why liquidity compensation is so high. However, keeping the tight spreads that TLLP providers are keeping is certainly not helping.

I don’t think we have an answer for dealing with week to week btc price swings. I think we should make it clear that you should only provide buy support if you think btc is going up week to week and only provide sell support if you think btc is gong down week to week. However, things like this are why my fiat pool is vastly more populated than my crypto pool on bter (among other factors)

1 Like

I though that was what being used and posted to express security concerns . After discussion with @Nagalim I found that TLLP use the same routine to get prices from third parties for both servers and clients, which eliminates the potential security problem. Would pushed prices you refer to introduce the said problem with trusting the server?

I think what he’s saying is that the push service would be a third party to the operator-client deal. So if the push service were compromised, it would indeed be a problem. This is similar to the issue of a compromised price feed, except that we will be creating the push service rather than relying on something like coindesk.

OK. We will see better when it comes out.

8 days ago, I ran nubot, support NuPool and NuPond 14000cny (8.05 BTC in poloniex, 2000 cny in bter), now only 7.92BTC in poloniex and 2000 cny in bter, interest 17.9NBT

Nubot is in operation 24 hours a day, but the funding was reduced to 98.3%

I think that something needs to change, very supportive of this motion


But cannot the custodian make more money than he or she loses because of btc’s volatility, by pocketing the spread each time there is a trade or by combining the pocketed spreads and the custodian fee provided by the pool?
Otherwise, I do not see how being a LPC can become a predictably profitable business. If liquidity provision is not predictably profitable, then Nu would not have any LPCs, hence it would mean the end of Nu.
So it is a crucial matter.

I never try to modify the parameters.
Could you let me know exactly which ones?

These numbers makes sense. I would like to try to shift terminology and instead of calling it spread, we could refer to offsets, sellprice in USD and buyprice in USD .
Offset = 0.05 $ , so we don’t leave anything to interpretation.

Good point, this is mitigated already since the first version of NuBot. Its probably poorly documented so I’ll try to make a very short summary (better documentation coming in next release).

The client-side (old) way (I speak for NuBot) :
NuBot requires at least 3 price feeds (for BTC it has actually 7 price feeds), one of which is considered “main” feed.

  • a process reads the price from these feeds every xx seconds.
  • mainfeed is cross compared with all the backup feeds to check if they are “inline”, within a certain tolerance.
  • if mainfeed is not “inline”, the following backup feed is taken as “main” and the same procedure repeated recursively.
  • at this point we have a “almost good price” . To further check if this is valid or results from a spoof/hack, the bot compares it with a moving average taken in a larger time window. If it pass the test the price is passed down to the trading strategy, if not orders are taken down and wait for the next cycle . If no good prices are found in 60 minutes, bot is shut down and email sent to custodian.

In the new way (0.3.1), we have the price servers doing those operations server side . When the server has a good price (that differs from the previous more than 0.x%) it pushes it to clients, along with an unique auth token.

The client (nubot) receive the command, verifies the token validity, and after that, tries to autonomously read from the third party price feeds to see if the value has been spoofed. If it is within a certain interval of confidence, walls are shifted, otherwise , well a bit of logic also here not worth mentioning.
I hope you get the picture .


There is no way to tell with certainty, only empirical experience, tight monitoring and adjustment can help.
It highly depends on how nubits are used by traders.

In my head, I depicted three kind of traders :

  1. trader that wants to buy/sell small medium amount of NBT to be used for useful purposes. (Buy online, pay someone, loans, betting, parking). I picture these user buying selling in the order of few times a month. These are our ideal users and we want to offer them NBT at a price as close to 1$ as possible to keep them in the loop. These kind of users must be protected and are source of small but positive revenue.

  2. hedging traders. They want to protect themselves from BTC volatility without going into fiat. They buy/sell mid-large quantities multiple times a week. Depending on how good they are with price forecasting, these traders can either bring losses (they are good) or profits (they are bad traders) to custodians.

  3. Malicious traders : traders who have found ways to take advantage of our walls by putting losses on custodians and taking a profit from themselves.

Now, when designing the spread and the bot pricing strategy, we must keep in mind that we want to make user 1 happy, take profit rather than losses from users 2, and mitigate damages coming from users 3. That is what the whole purpose of parametric order book is. Please remember that ultimately spotting those patterns is very challenging and we must be cautions.

A price offset is the easiest short term solution, but long term risks to make users 1 go away and users 2 and 3 getting better at exploiting our walls. Thin ice, the business of liquidity provision :wink:


Thanks for these details @desrever. It is exactly because all this thought has gone into the development of NuBot and the strategies it uses that I want to move towards using NuBot with the TLLPs. A lot of the issues we are seeing with the configuration of the TLLP clients has already been addressed in NuBot and, moving forward, there won’t be a duplication of effort, meaning that the development of the pool server can be focused on.


Just like to add that implementing different spreads and setting on th server site specific to the fees on each exchanges will require a separate instance of TLLP to be run as far as I can see. Haven’t tested running two TLLP threads on 1 server yet but it is difficult with the ports and Cloudflare security. Lacking the time to do that sort of testing at the moment (preparing for Android wallet). Running two servers would make things more expensive to run.
Given the situation/discussion here and earlier outages/issues with LiquidBits/CCEDK I’m considering to continue a bit longer with the current settings or temporarily cease some or all operations on LiquidBits.

Tks for detailing your thoughts.

It probably corresponds to the spreads that dynamically adjustment themselves depending on the market conditions (link).

Could you describe the main principles behind dynamic spread?
In other words, in which circumstance does the bot reduce the spread and increase the spread?
I think this is very relevant to this thread.

I see what you mean but let us say we realize that we are losing type 1 users because of a too large spread.
In that case we can respond to the situation rapidly and decrease accordingly.
So there is not much risk starting at a larger level than now.
We cannot know how the market would react without proposing figures in the first place.

1 Like

Its up for discussion and I wish I can get as many inputs as possible from experienced traders.

In its simplest and intuitive form, the higher the volatility, the higher the spread.
In a more complex form it should also take into account trading activity on the specific pair and various parameters linked to it (average order size, order frequency, day/hour/minute volumes … ) .
In its most sophisticated form, run a machine learning algorithm that learns from experience. This will require more time to aquire training data.

1 Like