---
# System prepended metadata

title: 網格買/賣單數量計算

---

# 網格買/賣單數量計算

- base_diff_ratio :
  - 此值動態計算得到, 如果大於1則設定為1 
  -  網格預估需要的base數量與實際外站能買到base數量比例 
  - ex: 網格預估5顆 但實際外站買到4.5顆, - base_diff_ratio = (4.5 / 5) = 0.9
  
 -  各價位點計算
```py
def round_to_rule(value: float, rule: str) -> float:
    return round(value, int(rule))


def round_to_rule_floor(n, decimals=0):
    multiplier = 10 ** int(decimals)
    return math.floor(n * multiplier) / multiplier

# 網格間距
grid_step = round_to_rule_floor((upper_limit - lower_limit) / float(grid_count), quotePrecision) 

price_points = []
price_points.append(upper_limit)
while True:
    price_point = round_to_rule(price_points[-1] - grid_step, quotePrecision)

    if upper_limit >= price_point and price_point >= lower_limit:
        price_points.append(price_point)

    if price_point <= lower_limit:
        print(f"各價位點:{price_points}")
        break

```

## 全買單  (現價 > 上限) 
`註: 全買單沒有站外買幣需要因此 base_diff_ratio 固定為1`
```
current_price = 658990 
capital = 1000 
grid_count = 2 
upper_limit = 4 
lower_limit = 1 
base_diff_ratio = 1
```

```
# capital = capital * base_diff_ratio * 0.998;  
1000 * 1 * 0.998 = 998

# grid_position = capital / (SUM(各價位點, 不包含最下面那格)  
round(998 / (4+3+2), 8) = 110.88888888888889

# fee = (grid_position * 最高價 * 0.002 * grid_count) + (1 * grid_count) 
(110.88888888888889 * 4 * 0.002 * 2) + (1 * 2) = 3.774222222222222

# capital = capital - fee  
(998 - 3.774222222222222) = 994.2257777777778

# grid_position = capital / (SUM(各價位點, 不包含最下面那格)  
round(994.2257777777778 / (4+3+2), 8) = 110.46953086
```

## 全賣單  (現價 < 下限) 

`註: 全賣單會先預扣買單所需要手續費 `

```
current_price = 658990 
capital = 1000 
grid_count = 2 
upper_limit = 800000 
lower_limit = 700000 
base_diff_ratio = 1.0894263392162356
```

```
# grid_position = capital / (SUM(各價位點, 不包含最下面那格) 
round(1000 / (800000 + 750000), 8) = 0.00064516

# fee = (grid_position * 最高價 * 0.002 * grid_count) + (1 * grid_count)  
(0.00064516 * 800000 * 0.002 * 2) + (1 * 2) = 4.064512000000001

# capital = (capital - fee) * 1 * 0.998;    # base_diff_ratio 大於1則設定為1
(1000 - 4.064512000000001) * 1 * 0.998 = 993.943617024

# grid_position = capital / (SUM(各價位點, 不包含最下面那格) 
round(993.943617024 / (800000 + 750000), 8) = 0.00064125
```

## 部份買單/賣單 (上限> 現價 >下限) 

```
current_price = 658990 
capital = 1000 
grid_count = 2 
upper_limit = 800000 
lower_limit = 600000 
base_diff_ratio = 0.86
```

```
# capital = capital * base_diff_ratio * 0.998
(1000 * 0.86 * 0.998) = 858.28

# grid_position = capital / (SUM(各價位點, 不包含最下面那格)  
round(858.28 / (800000 + 700000), 8) = 0.00057219

# fee = (grid_position * 最高價 * 0.002 * grid_count) + (1 * grid_count) 
(0.00057219 * 800000 * 0.002 * 2) + (1 * 2) = 3.8310079999999997

# capital = capital - fee  
(858.28 - 3.8310079999999997) = 854.448992

# grid_position = capital / (SUM(各價位點, 不包含最下面那格)
round(854.448992 / (800000 + 700000), 8) = 0.00056963
```
# 網格顆數計算

```py
import math


def round_to_rule(value: float, rule: str) -> float:
    return round(value, int(rule))


def round_to_rule_floor(n, decimals=0):
    multiplier = 10 ** int(decimals)
    return math.floor(n * multiplier) / multiplier


def get_fee(upper_limit, lower_limit, grid_count, basePrecision, quotePrecision):
    price_points = []
    grid_step = round_to_rule_floor(
        (upper_limit - lower_limit) / float(grid_count), quotePrecision
    )
    print(f"grid step:{grid_step}")
    price_points.append(upper_limit)
    while True:
        price_point = round_to_rule(price_points[-1] - grid_step, quotePrecision)

        if upper_limit >= price_point and price_point >= lower_limit:
            price_points.append(price_point)

        if price_point <= lower_limit:
            print(f"各價位點:{price_points}")
            break

    # round(998 / (200000+ 160080.0+ 120160.0+ 80240.0+ 40320.0), 8) = 0.00166112
    grid_position = round_to_rule(capital / sum(price_points[:-1]), basePrecision)
    # print(grid_position)
    return (
        (grid_position * price_points[0] * 0.002 * grid_count) + (1 * grid_count),
        price_points,
    )


def get_grid_position(
    capital, upper_limit, lower_limit, grid_count, basePrecision, quotePrecision
):
    fee, price_points = get_fee(
        upper_limit, lower_limit, grid_count, basePrecision, quotePrecision
    )
    # 資金扣除預留手續費
    # 998 - ((0.0016611185086551265 * 200000 * 0.002 * 5) + (1+5)) = 988.6777629826897
    if current_price < lower_limit:
        fee = 0

    print(f"get_grid_position fee:{fee}")
    capital = capital - fee
    print(f"扣除手續費後的資金:{capital}")

    # 扣掉預留費用，每格該下的btc數量，之後下單以這個為準
    grid_position = round_to_rule(capital / sum(price_points[:-1]), basePrecision)
    return grid_position


if __name__ == "__main__":
    current_price = # Test Log - base price bitopro
    capital = 1000
    grid_count = 2
    upper_limit = 800000
    lower_limit = 600000
    base_diff_ratio = # Test Log - base difference ratio
    basePrecision = 8
    quotePrecision = 0
    fee = 0

    # 目前價格小於網格最低價
    if current_price < lower_limit:
        fee, _ = get_fee(
            upper_limit, lower_limit, grid_count, basePrecision, quotePrecision
        )

    if base_diff_ratio > 1.0:
        capital = (capital - fee) * 0.998
    else:
        capital = (capital - fee) * base_diff_ratio * 0.998

    print(f"capital:{capital}, fee:{fee}")
    grid_position = get_grid_position(
        capital, upper_limit, lower_limit, grid_count, basePrecision, quotePrecision
    )
    print(f"grid position:{grid_position}")
```