Loading ...

Python 双平台对冲策略

Author: Zero, Date: 2016-09-06 13:04:00
Tags: Python Hedge

Python 双平台对冲策略


'''backtest
start: 2019-09-08 00:00:00
end: 2019-10-07 00:00:00
period: 1h
exchanges: [{"eid":"Bitfinex","currency":"BTC_USD"},{"eid":"Binance","currency":"BTC_USDT"}]
'''

import time
import json

def cancelAll():
    ret = False
    for e in exchanges:
        while True:
            n = 0
            for order in _C(e.GetOrders):
                ret = True
                e.CancelOrder(order.Id)
                n+=1
            if n == 0:
                break
    return ret

def main():
    global MinSpreadA, MinSpreadB
    SetErrorFilter("canceled")
    if len(exchanges) != 2:
        raise Exception("只支持两个交易所对冲")
    
    LogReset()
    LogProfitReset()
    cancelAll()
    
    initStocks = 0.0
    initBalance = 0.0
    minAmount = 0.1
    lastTradeTime = 0
    lastTradeErrExchange = ''
    accountsCache = []
    hedgeNum = [0, 0]
    names = []
    baseCurrency = exchange.GetCurrency()
    for e in exchanges:
        if e.GetCurrency().replace('USDT', 'USD') != baseCurrency.replace('USDT', 'USD'):
            raise Exception("必须是同样的货币才可以对冲 " + baseCurrency)
        names.append(e.GetName())
        account = _C(e.GetAccount)
        accountsCache.append(account)
        initStocks += account.Stocks
        initBalance += account.Balance
    minAmount = 0.01 if baseCurrency == "BTC" else 0.1
    Log("总钱:", _N(initBalance), "总币", _N(initStocks), 'Python:', __import__('sys').version)
    while True:
        if not accountsCache:
            accountsCache = [_C(e.GetAccount) for e in exchanges]
        Sleep(LoopInterval)
        cmd = GetCommand()
        if cmd:
            Log("CMD", cmd)
            arr = cmd.split(':')
            if arr[0] == 'A->B':
                MinSpreadA = float(arr[1])
            elif arr[0] == 'B->A':
                MinSpreadB = float(arr[1])
                
        depthA = exchanges[0].GetDepth()
        if not depthA:
            continue
        depthB = exchanges[1].GetDepth()
        if not depthB:
            continue
        if lastTradeTime > 0 and time.time() - lastTradeTime > BalanceTime:
            needUpdate = cancelAll()
            if not needUpdate:
                for account in accountsCache:
                    if account.FrozenBalance >= 0.1 or account.FrozenStocks > 0.001:
                        needUpdate = True
                        break
            if needUpdate:            
                accountsCache = [_C(e.GetAccount) for e in exchanges]
            nowStocks = 0.0
            nowBalance = 0.0
            for account in accountsCache:
                nowStocks += account.Stocks
                nowBalance += account.Balance
            diff = _N(nowStocks - initStocks, 5)
            isReverse = None
            if abs(diff) < minAmount:
                LogProfit(_N(nowBalance-initBalance, 3), "总钱:", _N(nowBalance), "总币", _N(nowStocks), "币差:", diff)
                lastTradeTime = 0
            elif diff > minAmount:
                isReverse = depthA.Bids[0].Price < depthB.Bids[0].Price
            elif -diff > minAmount:
                isReverse = depthA.Asks[0].Price > depthB.Asks[0].Price
            if isReverse is not None:
                depths = [depthA, depthB]
                opAmount = None
                for pos in ([1, 0] if isReverse else [0, 1]):
                    if diff >= minAmount:
                        opAmount = min(diff, accountsCache[pos].Stocks, depths[pos].Bids[0].Amount + depths[pos].Bids[1].Amount)
                        diff -= opAmount
                        if opAmount >= minAmount:
                            exchanges[pos].Sell(depths[pos].Bids[1].Price, opAmount)
                    elif -diff >= minAmount:
                        opAmount = min(-diff, _N(accountsCache[pos].Balance / depths[pos].Asks[1].Price, 3), depths[pos].Asks[0].Amount + depths[pos].Asks[1].Amount)
                        diff += opAmount
                        if opAmount >= minAmount:
                            exchanges[pos].Buy(depths[pos].Asks[1].Price, opAmount)
                if opAmount is not None:
                    lastTradeTime = time.time()
                    accountsCache = []
            continue
            # end of balanceAccount

        diffA = _N(depthA.Bids[0].Price - depthB.Asks[0].Price, 3)
        diffB = _N(depthB.Bids[0].Price - depthA.Asks[0].Price, 3)
        LogStatus('`' + json.dumps({'type': 'table', 'title': '运行信息', 'cols': ['名称', '钱', '冻结的钱', '币', '冻结的币', '买一', '卖一', '阀值', '差价', '次数'], 'rows': [[names[0], accountsCache[0].Balance, accountsCache[0].FrozenBalance, accountsCache[0].Stocks, accountsCache[0].FrozenStocks, depthA.Bids[0].Price, depthA.Asks[0].Price, MinSpreadA, diffA, hedgeNum[0]], [names[1], accountsCache[1].Balance, accountsCache[1].FrozenBalance, accountsCache[1].Stocks, accountsCache[1].FrozenStocks, depthB.Bids[0].Price, depthB.Asks[0].Price, MinSpreadB, diffB, hedgeNum[0]]]}) + '`')
        HPos = 0
        if diffA >= MinSpreadA:
            orderH = depthA.Bids[0]
            orderL = depthB.Asks[0]
            exchangeH = exchanges[0]
            exchangeL = exchanges[1]
            accountH = accountsCache[0]
            accountL = accountsCache[1]
        elif diffB >= MinSpreadB:
            HPos = 1
            orderH = depthB.Bids[0]
            orderL = depthA.Asks[0]
            exchangeH = exchanges[1]
            exchangeL = exchanges[0]
            accountH = accountsCache[1]
            accountL = accountsCache[0]
        else:
            continue

        opPrice = _N((orderH.Price + orderL.Price) / 2.0, 2)
        opAmount = min(MaxAmount, orderH.Amount, orderL.Amount, accountH.Stocks, _N(accountL.Balance / opPrice, 3))
        if opAmount >= minAmount:
            tasks = [[exchangeH.Sell, "H"], [exchangeL.Buy, "L"]]
            if lastTradeErrExchange == "L":
                tasks.reverse()
            lastTradeErrExchange = ""
            for task in tasks:
                if task[0](opPrice, opAmount) is None:
                    lastTradeErrExchange = task[1]
                    break
            lastTradeTime = time.time()
            accountsCache = []
            hedgeNum[HPos] += 1



Related

More

THPC yes

THPC nice

rty233 e.IO("websocket") 梦总 这句是什么意思 api文档里面没有啊