Basic Grid Trading Strategy
Implementation of basic grid trading strategy This is not the optimal version at present. I am currently running Binance's WebSocket version. If needed, I can change Binance's WebSocket version to one that runs on…
Implementation of basic grid trading strategy
This is not the optimal version at present. I am currently running Binance's WebSocket version. If needed, I can change Binance's WebSocket version to one that runs on the Inventor.
Parameters
| Name | Default | What it controls |
|---|---|---|
| trading_pair | BTC_USDT | trading pair |
| lower_price | false | Range lower limit price |
| upper_price | false | Range upper limit price |
| grid_num | 2 | Number of Grids |
| trading_per_grid | false | Purchase quantity per grid |
| price_precision | 2 | Order price accuracy |
| amount_precision | 5 | Order quantity precision |
Source Python
'''backtest
start: 2021-08-01 00:00:00
end: 2021-09-01 00:00:00
period: 1m
basePeriod: 1m
exchanges: [{"eid":"Binance","currency":"BTC_USDT","balance":1000000,"stocks":0,"fee":[0.06,0.075]}]
args: [["lower_price",30000],["upper_price",50000],["grid_num",200],["trading_per_grid",0.1]]
'''
grid = dict()
interval = 0
class GridItem:
def __init__(self, order_id, status, price):
self.order_id = order_id
self.status = status # -1:This point is blank; -2: no order has been placed at this point
self.side = 0 # 1:Buy; 2: Sell; 0: Unknown
self.price = price
def create_grid(ticker_price):
global grid
global interval
exchange.SetCurrency(trading_pair)
exchange.SetPrecision(price_precision, amount_precision)
interval = _N((upper_price - lower_price) / grid_num, price_precision)
grid[lower_price] = GridItem(-1, -2, lower_price)
grid[upper_price] = GridItem(-1, -2, upper_price)
for i in range(1, grid_num):
price = lower_price + interval * i
grid[price] = GridItem(-1, -2, price)
buy_stocks = (grid_num - int((ticker_price - lower_price) / interval) - 1) * trading_per_grid
buy_2_sell(buy_stocks)
def buy_2_sell(buy_stocks):
while True:
account = exchange.GetAccount()
stocks = _N(account['Stocks'], amount_precision)
if stocks < buy_stocks:
depth = exchange.GetDepth()
price = depth['Asks'][0]['Price']
vol = _N(price * trading_per_grid, price_precision)
min_vol = 1.0 / (10 ** price_precision)
exchange.Buy(-1, vol if vol > min_vol else min_vol)
else:
break
Sleep(1000)
def set_blank(price):
grid[price].order_id = -1
grid[price].status = -1
grid[price].side = 0
def update_order():
last_blank_price = -1
close_price_list = set()
for grid_item in grid.values():
if grid_item.status == -1:
last_blank_price = grid_item.price
elif grid_item.status == -2:
close_price_list.add(grid_item.price)
else:
order = exchange.GetOrder(grid_item.order_id)
grid_item.status = order["Status"]
if grid_item.status == 1:
close_price_list.add(grid_item.price)
return close_price_list, last_blank_price
def remove_blank(close_price_list, last_blank_price):
if last_blank_price != -1:
close_price_list.discard(last_blank_price)
def set_left_blank(close_price_list, left_side_grid, last_blank_price):
set_blank(left_side_grid)
close_price_list.discard(left_side_grid)
if last_blank_price != -1:
close_price_list.add(last_blank_price)
def set_right_blank(close_price_list, right_side_grid, last_blank_price):
set_blank(right_side_grid)
close_price_list.discard(right_side_grid)
if last_blank_price != -1:
close_price_list.add(last_blank_price)
def trace():
close_price_list, last_blank_price = update_order()
has_buy_order = False
for price in close_price_list:
if grid[price].side == 1:
has_buy_order = True
break
if has_buy_order:
ticker_price = min(close_price_list) - interval / 2.0
else:
ticker = exchange.GetTicker()
ticker_price = ticker['Last']
if not grid:
create_grid(ticker_price)
left_side_grid = int((ticker_price - lower_price) / interval) * interval + lower_price
right_side_grid = left_side_grid + interval
# Set blank points
# There is no transaction on the left side of the current price and no transaction on the right side of the current price. It does not exist.
# The blank point on the left side of the current price and the blank point on the right side of the current price do not exist.
# If either the left or right side is blank, there is no need to update the blank point
if left_side_grid >= upper_price or right_side_grid <= lower_price:
# Outside the range, no blank points are needed
remove_blank(close_price_list, last_blank_price)
elif grid[left_side_grid].status == 0 and grid[right_side_grid].status == 1:
set_right_blank(close_price_list, right_side_grid, last_blank_price)
elif grid[left_side_grid].status == 1 and grid[right_side_grid].status == 0:
set_left_blank(close_price_list, left_side_grid, last_blank_price)
elif grid[left_side_grid].status == 1 and grid[right_side_grid].status == 1:
set_right_blank(close_price_list, right_side_grid, last_blank_price)
elif grid[left_side_grid].status == -2 and grid[right_side_grid].status == -2:
set_right_blank(close_price_list, right_side_grid, last_blank_price)
# Place an order again
for price in close_price_list:
if price <= ticker_price:
order_id = exchange.Buy(price, trading_per_grid)
side = 1
else:
buy_2_sell(trading_per_grid)
order_id = exchange.Sell(price, trading_per_grid)
side = 2
if order_id:
grid[price].order_id = order_id
grid[price].status = 0
grid[price].side = side
def main():
while True:
trace()
Sleep(1000)
Published by xl9211 on the FMZ strategy square · last modified 2021-09-27. Collected in the Quant Trading Vault. Unvalidated research: re-test with your own data and costs before trusting it.
Build this with AgenKit
A spec is not a trading system. Paste this into your coding agent and AgenKit runs a specialist team — architecture, test-first build, risk gates, review — with paper trading on by default.
/agenkit build a grid bot with inventory caps and order deduplication from strategies/Basic-Grid-Trading-Strategy.md- npx agenkit install engineering-kit in your project
- Paste the command into your agent and approve each phase
- Get tests, backtest, risk controls and a paper-trading switch
Understand it first
Before you run this, read the lesson behind the idea and how to backtest it honestly. Specs like this one are the survivors of an unknown number of trials; deflate their results accordingly.