風險控制
需要將倉位杠桿控制到3倍以內,由于dydx與apex沒有獲取倉位杠桿的接口,但是每次發送交易的數額可以決定,故而可以設置每次發送總倉位1.5倍杠桿的數額,然后設置一個變量保證每個方向上的交易不超過2次,即可保證總倉位始終小于3倍杠桿
細節:
send_order_apex(client_apex, symbol=“BTC-USDC”, side=“BUY”,type=“MARKET”,size=“0.004”, expirationEpochSeconds=currentTime+100,price=’58888’, limitFeeRate=limitFeeRate)
在apex市價交易參數里,price代表可接受的價格,故而當賣出時,此price要盡可能的調低,否則會失敗,同理買進時要盡可能的高。
同時將價差計算修改為:
?# 計算價差
? ? spread1 = ((float(b_first_price_apex) -float(s_first_price_dydx))/float(b_first_price_apex))*100
? ? spread2 = ((float(b_first_price_dydx) - float(s_first_price_apex))/float(b_first_price_dydx))*100?
因為如果在apex賣,dydx買的話,apex的賣價應該大于dydx的買價,apex的賣價由apex買一價決定,dydx買價由dydx賣一價決定。反之同理。
代碼修改如下:
get_depth_data_btc.py
"""
這是一個用來計算 APEX 和 dydx 之間的 BTCUSDC 價差的模塊。
可以調用 calculate_spread 函數來返回兩個交易所的賣一價、買一價和價差。
"""import asyncio
from apexpro.http_public import HttpPublic
from dydx3 import Client
from dydx3.constants import MARKET_BTC_USD# 定義交易對列表
symbol = 'BTCUSDC'
market = MARKET_BTC_USD# 定義異步函數來獲取 APEX 的價格
async def get_apex_price():# 初始化API客戶端apexclient = HttpPublic("https://pro.apex.exchange")# 獲取深度數據trades_data = apexclient.depth(symbol=symbol)['data']# 返回賣一價和買一價return trades_data['a'][0][0], trades_data['b'][0][0], trades_data['a'][0][1], trades_data['b'][0][1]# 定義異步函數來獲取 dydx 的價格
async def get_dydx_price():# 初始化API客戶端dydxclient = Client(host='https://api.dydx.exchange')# 獲取深度數據orderbook_response = dydxclient.public.get_orderbook(market=market)orderbook_data = orderbook_response.data# 返回賣一價和買一價return orderbook_data['asks'][0]['price'], orderbook_data['bids'][0]['price'], orderbook_data['asks'][0]['size'], orderbook_data['bids'][0]['size']# 定義異步函數來計算價差
async def calculate_spread():# 創建兩個任務,分別獲取 APEX 和 dydx 的價格task1 = asyncio.create_task(get_apex_price())task2 = asyncio.create_task(get_dydx_price())# 等待兩個任務完成,并獲取結果s_first_price_apex, b_first_price_apex,s_first_size_apex,b_first_size_apex = await task1s_first_price_dydx, b_first_price_dydx,s_first_size_dydx,b_first_size_dydx = await task2# 計算價差spread1 = ((float(b_first_price_apex) - float(s_first_price_dydx))/float(b_first_price_apex))*100spread2 = ((float(b_first_price_dydx) - float(s_first_price_apex))/float(b_first_price_dydx))*100return s_first_price_apex,b_first_price_apex,s_first_price_dydx,b_first_price_dydx,s_first_size_apex,b_first_size_apex,s_first_size_dydx,b_first_size_dydx,spread1,spread2if __name__ == '__main__':# 創建事件循環loop = asyncio.get_event_loop()# 運行異步函數loop.run_until_complete(calculate_spread())# 關閉事件循環loop.close()
place_order_btc.py
from init_apex_client import init_client
import asyncio
from send_order_apex import send_order_apex
from init_dydx_client import init_dydx_client
from send_order_dydx import send_order_dydx
from dydx3.constants import MARKET_BTC_USD
from dydx3.constants import ORDER_SIDE_BUY,ORDER_SIDE_SELL
from dydx3.constants import ORDER_TYPE_MARKET,ORDER_TYPE_LIMIT
from get_depth_data_btc import calculate_spread
import time#價格設置需要更精確,不然發不出去!# 初始化apex客戶端
client_apex = init_client()
configs = client_apex.configs()
# 獲取apex用戶和賬戶信息
client_apex.get_user()
client_apex.get_account()# 初始化dydx客戶端
client_dydx = init_dydx_client()
# 獲取我們的dydx倉位 ID
account_response = client_dydx.private.get_account()
position_id = account_response.data['account']['positionId']async def arbitrage():arbitrage_count = 0while True:# 計算價差s_first_price_apex,b_first_price_apex,s_first_price_dydx,b_first_price_dydx,s_first_size_apex,b_first_size_apex,s_first_size_dydx,b_first_size_dydx,spread1,spread2 = await calculate_spread()# 根據價差判斷是否發送交易if spread1 > 0.7:if arbitrage_count <2:currentTime = time.time()limitFeeRate = client_apex.account['takerFeeRate']task_apex_sell = asyncio.create_task(send_order_apex(client_apex, symbol="BTC-USDC", side="SELL",type="MARKET", size="0.004", expirationEpochSeconds=currentTime+100,price='18888', limitFeeRate=limitFeeRate))task_dydx_buy = asyncio.create_task(send_order_dydx(client_dydx, position_id, MARKET_BTC_USD, ORDER_SIDE_BUY, ORDER_TYPE_LIMIT,True, '0.004', b_first_price_dydx, '0.0015', currentTime+100))orderResult1 = await task_apex_sellorderResult2 = await task_dydx_buyarbitrage_count += 1if arbitrage_count >=2:print('above leverage ,stop')print(orderResult1,orderResult2)if spread2 > 0.7: if arbitrage_count >-2:currentTime = time.time()# 異步地發送一個apex市價買單和一個dydx市價賣單limitFeeRate = client_apex.account['takerFeeRate']task_apex_buy = asyncio.create_task(send_order_apex(client_apex, symbol="BTC-USDC", side="BUY",type="MARKET", size="0.004", expirationEpochSeconds=currentTime+100,price='58888', limitFeeRate=limitFeeRate))task_dydx_sell = asyncio.create_task(send_order_dydx(client_dydx, position_id, MARKET_BTC_USD, ORDER_SIDE_SELL, ORDER_TYPE_LIMIT,True, '0.004', s_first_price_dydx, '0.0015', currentTime+100))orderResult1 = await task_apex_buyorderResult2 = await task_dydx_sellarbitrage_count -= 1if arbitrage_count <=-2:print('above leverage ,stop')print(orderResult1,orderResult2)# 延時一秒,避免過于頻繁await asyncio.sleep(1)# 運行異步函數
asyncio.run(arbitrage())
持續運行:
寫一個腳本確保因為各種異常程序退出后能夠重啟:
import subprocess
import timedef run_program():# 這里替換為你需要執行的程序命令process = subprocess.Popen(["python", "place_order_btc.py"]) # 例如:python your_program.pyreturn processif __name__ == "__main__":while True:program = run_program()while program.poll() is None:# 程序正在運行time.sleep(5) # 每5秒檢查一次程序狀態# 程序已終止,等待一段時間后重啟print("程序已終止,重新啟動中...")time.sleep(3) # 等待3秒