Binance API response shows wrong minimum order quantity - trading

Trying to hit the fapi.binance.com/fapi/v1/exchangeInfo endpoint in order to get the current minimum order quantity for a pair (let's take ETHUSDT as an example).
Here is what Binance UI shows as the minQty: Minimum order quantity for ETH is 0.004ETH
When hitting the above mentioned endpoint and inspecting the ETHUSDT symbol specific response:
{
"symbol": "ETHUSDT",
"pair": "ETHUSDT",
"contractType": "PERPETUAL",
"deliveryDate": 4133404800000,
"onboardDate": 1569398400000,
"status": "TRADING",
"maintMarginPercent": "2.5000",
"requiredMarginPercent": "5.0000",
"baseAsset": "ETH",
"quoteAsset": "USDT",
"marginAsset": "USDT",
"pricePrecision": 2,
"quantityPrecision": 3,
"baseAssetPrecision": 8,
"quotePrecision": 8,
"underlyingType": "COIN",
"underlyingSubType": [
"Layer-1"
],
"settlePlan": 0,
"triggerProtect": "0.0500",
"liquidationFee": "0.015000",
"marketTakeBound": "0.05",
"filters": [
{
"minPrice": "39.86",
"maxPrice": "306177",
"filterType": "PRICE_FILTER",
"tickSize": "0.01"
},
{
"stepSize": "0.001",
"filterType": "LOT_SIZE",
"maxQty": "10000",
"minQty": "0.001"
},
{
"stepSize": "0.001",
"filterType": "MARKET_LOT_SIZE",
"maxQty": "2000",
"minQty": "0.001"
},
{
"limit": 200,
"filterType": "MAX_NUM_ORDERS"
},
{
"limit": 10,
"filterType": "MAX_NUM_ALGO_ORDERS"
},
{
"notional": "5",
"filterType": "MIN_NOTIONAL"
},
{
"multiplierDown": "0.9500",
"multiplierUp": "1.0500",
"multiplierDecimal": "4",
"filterType": "PERCENT_PRICE"
}
],
"orderTypes": [
"LIMIT",
"MARKET",
"STOP",
"STOP_MARKET",
"TAKE_PROFIT",
"TAKE_PROFIT_MARKET",
"TRAILING_STOP_MARKET"
],
"timeInForce": [
"GTC",
"IOC",
"FOK",
"GTX"
]
}
We can observe that no data here indicates a correct minQty despite the fact that some documents in the filters array (like LOT_SIZE and MARKET_LOT_SIZE) are trying.
Am I missing something or is this a Binance API bug?

Took a while to figure it out, but I believe I have come to a solution/explanation.
As I previously noted, we are interested in the filters array found in the response of the fapi.binance.com/fapi/v1/exchangeInfo endpoint, specifically the MARKET_LOT_SIZE (LOT_SIZE if you are not interested in market orders) and MIN_NOTIONAL filters. When I wrote the question I assumed one of those had to be the source of truth, but none of the two were consistently matching the minimum order quantities seen on Binance UI.
It turns out its not one of them, but the two combined...sort of.
For inexperienced traders - a quick definition. Base asset - the asset you are buying. Quote asset - the asset you are acquiring the base asset with. In my case (ETHUSDT) ETH was the base asset and USDT was the quote asset.
MIN_NOTIONAL filter tells you the minimum amount of the quote asset you are required to spend to acquire the base asset. This filter is equal to 5 USDT in the case of ETHUSDT at the time of posting.
MARKET_LOT_SIZE filter tells you the minimum amount of the base asset you can buy. This filter is equal to 0.001 in the case of ETHUSDT at the time of posting.
Depending on the price of ETH, 0.001 ETH may cost less than 5 USDT, which would not fill the MIN_NOTIONAL filter's requirement. Similarly, if, due to price, 5 USDT bought less than 0.001 ETH, an order with notional value of 5 USDT would not fill the requirement of the MARKET_LOT_SIZE filter.
Hence, to calculate the minimum order quantity, we need to take the maximum value of the two with one caveat. We first need to convert the MIN_NOTIONAL filter value of 5 USDT to ETH. We can do that by dividing that value by the current price of ETH. Beware, if the result of the division has more decimal points then the quantity precision of the asset on Binance, we need to round up to that number of decimals.
Ultimately, the calculation example in Python:
max(
MIN_MARKET_LOT_SIZE,
round_up((MIN_NOTIONAL / CURRENT_ETH_PRICE), ETH_QUANTITY_PRECISION)
)
An example of the decimal rounding up function can be found here

Below calculation worked for me.
Divide MIN_NOTIONAL value with the current price of symbol to get the minimum quantity to place the order
minQty = MIN_NOTIONAL / current price of symbol
In my case,
MIN_NOTIONAL value was 5.0,
I have used 5.5, just to place the order more than the minimum quantity
use um_futures_client.mark_price(symbol) to get the mark price
Thanks

Related

Why does the buy operation not change the account balance despite quote currency being available (after sell opertaion commenced first)?

if condition2 < condition1:
# Call the function to get the account balances
balances = get_balances()
quote_balance = balances['quote']
base1_balance = balances['base1']
base2_balance = balances['base2']
now = int(time.time() * 1000)
url_sell = 'https://api.kucoin.com/api/v1/orders'
# Generate a unique clientOid
client0id = str(uuid.uuid4())
# Calculate the size based on the baseIncrement and baseMinSize
baseMinSize = 0.1
baseIncrement = 0.0001
a = base1_balance
decimal_val = decimal.Decimal(str(a)).quantize(
decimal.Decimal('.000001'),
rounding=decimal.ROUND_DOWN
)
size_base1 = float(decimal_val)
data_sell = {
"clientOid": client0id,
"side": "sell",
"symbol": "BASE1-QUOTE",
"size": size_base1,
"type": "market",
"price": ""
}
str_to_sign_sell = str(now) + 'POST' + '/api/v1/orders' + json.dumps(data_sell)
signature_sell = base64.b64encode(
hmac.new(api_secret.encode('utf-8'), str_to_sign_sell.encode('utf-8'), hashlib.sha256).digest())
passphrase_sell = base64.b64encode(
hmac.new(api_secret.encode('utf-8'), api_passphrase.encode('utf-8'), hashlib.sha256).digest())
headers_sell = {
"Content-Type": "application/json",
"KC-API-SIGN": signature_sell,
"KC-API-TIMESTAMP": str(now),
"KC-API-KEY": api_key,
"KC-API-PASSPHRASE": passphrase_sell,
"KC-API-KEY-VERSION": "2"
}
response_sell = requests.request('post', url_sell, headers=headers_sell, data=json.dumps(data_sell))
print(response_sell.status_code)
# wait 10 seconds before looping again
while True:
time.sleep(10)
break
# Call the function to get the account balances
balances = get_balances()
now = int(time.time() * 1000)
url_buy = 'https://api.kucoin.com/api/v1/orders'
# Generate a unique clientOid
client0id = str(uuid.uuid4())
# Calculate the funds based on the quoteIncrement and quoteMinSize
quoteMinSize = 0.1
quoteIncrement = 1
a = quote_balance
decimal_val = decimal.Decimal(str(a)).quantize(
decimal.Decimal('.1'),
rounding=decimal.ROUND_DOWN
)
funds_quote = float(decimal_val)
data_buy = {
"clientOid": client0id,
"side": "buy",
"symbol": "BASE2-QUOTE",
"funds": funds_quote,
"type": "market",
"price": ""
}
str_to_sign_buy = str(now) + 'POST' + '/api/v1/orders' + json.dumps(data_buy)
signature_buy = base64.b64encode(
hmac.new(api_secret.encode('utf-8'), str_to_sign_buy.encode('utf-8'), hashlib.sha256).digest())
passphrase_buy = base64.b64encode(
hmac.new(api_secret.encode('utf-8'), api_passphrase.encode('utf-8'), hashlib.sha256).digest())
headers_buy = {
"Content-Type": "application/json",
"KC-API-SIGN": signature_buy,
"KC-API-TIMESTAMP": str(now),
"KC-API-KEY": api_key,
"KC-API-PASSPHRASE": passphrase_buy,
"KC-API-KEY-VERSION": "2"
}
response_buy = requests.request('post', url_buy, headers=headers_buy, data=json.dumps(data_buy))
print(response_buy.status_code)
I'm having a strange problem with the fragment of code that i pasted here. It's a trading bot that's supposed to sell and buy given assets if certain conditions are met. All the rest of my code works as intended. The problem most likely lies somewhere within this fragment.
there are two base currencies and one quote currency
PROBLEM:
1st scenario:
base1 currency available --> sell proceed returns 200 --> balance reflects change in assets size --> quote currency available --> buy proceed returns 200 --> no change in balance of base2 currency
2nd scenario:
base1 currency unavailable --> sell proceed returns 200 --> obviously no change in asset size --> quote currency available --> buy proceed returns 200 --> filled with balances of base2 currency appropriately changed
what I want:
base1 currency unavailable/available --> sell proceed returns 200 --> filled with balances appropriatlely changed --> quote currency available --> buy proceed returns 200 --> filled with balances of base2 currency appropriately changed
The best way to describe the issue would be to give an example:
1st scenario:
1500 units of base1 currency
0 units of base2 currency
0 units of quote currency
*selling returns code 200 --> balance checked again --> balance changed *
now I have (let's say):
0 units of base1 currency
0 units of base2 currency
3500 units of quote currency
buying returns code 200 --> balance checked again --> balance not changed
finally I have (here's the problem) still:
0 units of base1 currency
0 units of base2 currency
3500 units of quote currency
2nd scenario:
0 units of base1 currency
0 units of base2 currency
3500 units of quote currency
selling returns code 200 --> balance checked again --> balance (obviously) not changed
now I have (let's say):
0 units of base1 currency
0 units of base2 currency
3500 units of quote currency
buying returns code 200 --> balance checked again --> balance changed
finally I have:
0 units of base1 currency
1500 units of base2 currency
0 units of quote currency
In other words:
if there is not enough base currency to make a sell operation then sell proceeds and then the buy operation proceeds with the account balance changing appropriately
while
if there is enough base currency to make a sell operation then sell proceeds and then the buy operation also proceeds but the account balance doesn't change
What could be the underlying cause of this issue?
I tried:
making pause between sell and buy operation longer - no result
trying to check if sell order was filled but it doesn't matter as the balance check after sell operation (if base currency available) shows that the sell operation did fill and quote currency is available for buying
indenting buying part of code more - no result
trying to change quote increment - no result

Trying to understand “PT1H” in a date-time string

I'm using the Weather API to pull weather information down as a service for my project. I'm trying to understand some timezone offsets that I can't seem to find information on.
The URL I'm using is:
https://api.weather.gov/gridpoints/VEF/154,48
Here is some sample return values:
"temperature": {
"sourceUnit": "F",
"uom": "unit:degC",
"values": [
{
"validTime": "2019-05-11T16:00:00+00:00/PT1H",
"value": 18.333333333333371
},
{
"validTime": "2019-05-12T04:00:00+00:00/PT2H",
"value": 16.1111111111112
},
{
"validTime": "2019-05-12T21:00:00+00:00/PT4H",
"value": 26.666666666666742
},
...
]
}
I understand the PT means Pacific Timezone. But I cant seem to find any information on the next to characters like 1H, 2H, etc.
If anyone can advise that would be appreciated - Thanks
PT1H = One hour
I understand the PT means Pacific Timezone.
No, incorrect assumption. Not a time zone.
The PT1H represents a duration, a span of time not tied to the timeline. This format is defined in the ISO 8601 standard.
The P marks the beginning, short for “Period” I imagine, a synonym for duration. The T separates any years-months-days portion from any hours-minutes-seconds portion.
So PT1H means “one hour”. Two and a half hours would be PT2H30M.
Parsing
Your input "2019-05-11T16:00:00+00:00/PT1H" combining a starting moment with a duration is part of the ISO 8601 standard.
Such a combo string can be parsed by the Interval.parse method found in the ThreeTen-Extra library.
Interval interval = Interval.parse( "2019-05-11T16:00:00+00:00/PT1H" ) ;
An Interval represents a pair of moments, a pair of Instant objects. In your case here, the second moment is calculated, by adding the duration to the starting moment. We can interrogate for the pair of moments, represented as Instant objects (always in UTC by definition).
Instant start = interval.getStart() ;
Instant stop = interval.getEnd() ;

Highcharts datalabels Float Number including Zero after dot: x.0 not only x (exact decimals as in inputdata)

If i enter 17.0for a data value, the datalabels displays only 17 (the ".0" is missing)
How to fix that?
Example:
Input: 17.1 -> ok, data.y = 17.1, dataLabel = 17.1
Input: 17.0 -> nok: data.y = 17, dataLabel = 17
(BTW: i do not mean do display always one number after dot, i need to have the exact value that i got, so it may also be 17.00 or 17.000, depending on the source)
In this example, in the tooltip of May, Serie 1, i need 144.0 displayed and in October, Series 2 in need 176.0, i mean the same "value" i see in the data-Array: http://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/highcharts/tooltip/formatter-shared/ (this is the second example linked here: http://api.highcharts.com/highcharts/tooltip.formatter )
You can create a simple condition inside tooltip's formatter, which will check if number have decimals. If not (e.g. 144), it will add one additional digit (0) as a decimal.
if (value.toString().indexOf('.') === -1) {
value = value.toFixed(1);
}
API Reference:
http://api.highcharts.com/highcharts/tooltip.formatter
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed
Example:
http://jsfiddle.net/k4nvjm29/

NETLOGO: Making network with exact number of links

I need to do the network when agents will be connected with links and i want it make so that there will be exact number (variable) of links going from each agent. Lets say for example that i want 3 links going from each agent to another. No more, no less. I was trying to use this code:
let num-links (links * number) / 2
while [count links < num-links ]
[
ask one-of turtles
[
let choice (min-one-of (other turtles with [not link-neighbor? myself])
[distance myself])
if choice != nobody [ create-link-with choice ]
]
]
Where "number" is the number of nodes and "links" is number of links i want to go from each agent- But this code unfortunately works so that "links" is really just an average degree of node. So if I want 3 links, i could get all agent (except for example two) with 3 links going from them, but one of them would have only 1 link and another 5 (average is 3 then). Is there some way How to do it.
And is there some way how to do it so that each "link" would be actually two directed links, one going from the node and one going to the node?
And one last question. I want to give this links a variable, but i need to do it so that sum of these variables from each agent is exactly 100 (as percents).
Any help? Thank you very much.
Here is how I create a fixed degree network for a small network (easy to understand)
to make-legal
create-turtles 100 [setxy random-xcor random-ycor]
let target-degree 5
while [ min [ count my-links ] of turtles < target-degree ]
[ ask links [die]
makeNW-Lattice target-degree
]
end
to makeNW-Lattice [DD]
ask turtles
[ let needed DD - count my-links
if needed > 0
[ let candidates other turtles with [ count my-links < DD ]
create-links-with n-of min (list needed count candidates) candidates
]
]
end
See NetLogo Efficient way to create fixed number of links for more efficient methods for larger networks.
Please ask separate questions for separate issues
UPDATE to ensure all nodes have required degree, in response to comment
Based on the following code, the basic generator does a legal network a little under 50% of the time. Therefore I simply threw the original code in a while loop and regenerated if not legal. This is not a good solution for larger networks, but is a reasonable hack.
to setup
let mins (list 0 0 0 0 0 0)
repeat 100
[ ask turtles [die]
ask links [die]
makeNW-lattice
let this-min min [ count my-links ] of turtles
set mins replace-item this-min mins (item this-min mins + 1)
]
print mins
end

How to calculate RPG Level Progression as percentage

I'm designing an RPG game where a user may accumulate experience points (XP) and level up, based on XP. Calculating the current level is trivial; if else seems to be most efficent.
I would like to calculate percent of progression for the current level. Based on the assumption that I have 10 levels, where each level is capped at a somewhat exponential value:
typedef NS_ENUM(NSInteger, RPGLevelCap) {
RPGLevelCap1=499,
RPGLevelCap2=1249,
RPGLevelCap3=2249,
RPGLevelCap4=3499,
RPGLevelCap5=4999,
RPGLevelCap6=6999,
RPGLevelCap7=9999,
RPGLevelCap8=14999,
RPGLevelCap9=19999,
RPGLevelCap10=19999 // Anything beyond previous level is Lvl 10; display as 100%
};
What's an efficient, yet easily understandable way, to calculate a user's level progression based on their current level?
An if else statement is both hard to understand and maintain, but may be fairly efficient:
float levelProgression=0;
// Calculate level progression as a fraction of 1
if(xp <= RPGLevelCap1)
{
levelProgression = ((float)xp / RPGLevelCap1);
}
else if (xp <=RPGLevelCap2)
{
levelProgression = ((float)(xp-RPGLevelCap1) / (RPGLevelCap2-RPGLevelCap1));
}
else if (xp <=RPGLevelCap3)
{
levelProgression = ((float)(xp-RPGLevelCap2) / (RPGLevelCap3-RPGLevelCap2));
}
...
else if (xp>RPGLevelCap10)
{
levelProgression = 1;
}
Given that the level caps are inconsistent...how should I handle this problem?
Hmm. A simple way would be to store the level cap values in an array. Find the player's current level based on the largest value it's less than. (level one is 0 to 499, level two is 500 to 1249, etc.) Use a loop to find the user's level rather than a set of if/else statements.
Then calculate the range of the player's current level, (end_of_range - start_of_range)
0 - 499 = 499
500 - 1249 = 749,
etc.
If a player is at 600 points, he's a level 2 character, in the 500-1249 range.
He's at 600-500 or 100 points into the range. (600-500)/749*100 is the player's percent complete in that range. 13.35% complete, in this example.
There are a few ways you can approach this. My weapon of choice here is to embody the XP values within the concept of LevelData versus using an enum, array of XP values, etc. The benefit of something like this is that for each level, you'll typically have many configurable values (for example level based multipliers) based on level. This way they are all in once place.
In your LevelData, there are different ways you can encode XP. These range from the XP total for the next level, or the beginning and end XP total for the next level. Obviously there are other permutations of this.
I usually use the later, mainly because it prevents me from having to "know" the LevelData for the previous level.
So I would typically have this in JSON
{
"levelData": [
{
"levelStartXP": "0",
"levelUpXP": "250",
"levelUpBonus": 0
},
{
"levelStartXP": "250",
"levelUpXP": "1000",
"levelUpBonus": 50
},
{
"levelStartXP": "1000",
"levelUpXP": "2500",
"levelUpBonus": 100
},
]
}
This is just a boring example. I then of course have a LevelData class which is embodies each level. I also have a LevelDataManager. That manager is used to vend out information per level. Having convenience methods help. For examples, good ones to have are:
- (NSInteger)levelWithXP:(NSInteger)xp; // for a given XP, give me the appropriate level
- (LevelData *)levelDataWithXP:(NSInteger)xp; //for a given XP, give me the appropriate LevelData
- (LevelData *)levelDataWithLevel:(NSInteger)level; // for a given level, give me the appropriate LevelData
- (NSInteger)levelUpXPForLevel:(NSInteger)level; // for a given level, give me the XP value needed for the next level)
I just arbitrarily used NSInteger, use the appropriate data type for your case.
Just what you want to support is really up to you.
The gist of the whole thing is try not to store individual level components. Rather aggregate them in LevelData or some other collection, so you have all the info per level at your disposal and create some form of manager/interface to get you the information you need.
So back to you your question. Let's say we have a class for LevelData (assume it is using the JSON above, and those fields are represented by properties) and a LevelDataManager instance called theLevelDataMgr, you could compute the % based on something like:
LevelData *levelData = [theLevelDataMgr levelDataWithLevel:currLevel]; // currLevel is the current level
float xpDiffInLevel = levelData.levelUpXP - levelStartXP;
float xpInLevel = currXP - levelStartXP; // currXP is the current XP of the user
float pctOfXP = xpInLevel / xpDiffInLevel; // You should add divide by zero check
And yes, if you wanted, you could have the LevelData class contain a method to do this calculation for you to help encapsulate it even better.
Code isn't tested and is listed to just give you a better idea on how to do it. Also, how you decide to store your XP for each level dictates how this would work. This code is based on the method I usually use.

Resources