avatar of ianzeng123 ianzeng123
집중하다 사신
2
집중하다
319
수행원

디지털 화폐 분야의 여러 그리드 전략에 대한 간략한 논의

만든 날짜: 2025-08-15 16:13:33, 업데이트 날짜: 2025-08-26 10:30:15
comments   0
hits   660

암호화폐 시장은 독특한 거래 환경을 제공하여 그리드 트레이딩 전략에 이상적인 적용 환경을 조성합니다. 기존 금융 시장과 달리 암호화폐 시장은 24시간 연중무휴로 운영되며, 가격 변동이 지속적이고 빈번하여 그리드 전략에 풍부한 차익거래 기회를 제공합니다. 또한, 현물 및 무기한 계약과 같은 주요 거래 상품은 만기 제한이 없어 트레이더들이 계약 만기 위험에 대한 걱정 없이 장기적으로 포지션을 유지할 수 있습니다. 암호화폐 시장의 높은 변동성과 상대적으로 높은 유동성은 그리드 전략을 실행하기에 유리한 조건을 제공합니다.

바로 이러한 특성 때문에 그리드 트레이딩 전략은 암호화폐 시장에서 강력한 적용 가능성과 수익 잠재력을 보여줍니다. 그리드 트레이딩은 암호화폐 시장에서 널리 사용되는 전략으로, 트레이더들이 시장 방향을 예측하지 않고도 시장 변동성을 활용하여 수익을 창출할 수 있도록 해줍니다. 다양한 가격대에서 매수 및 매도 주문을 함으로써, 그리드 트레이딩은 트레이더들이 가격 상승과 하락 모두에서 수익을 창출할 수 있도록 도와줍니다.

그리드 트레이딩 전략에는 다양한 변형이 있습니다. 이 글에서는 초보자들이 이 고전적인 양적 트레이딩 방식을 시작하는 데 도움이 되도록 몇 가지 형식만 간략하게 살펴보겠습니다. 그리드 트레이딩 전략의 핵심은 서로 다른 가격 수준에서 일련의 매수 및 매도 주문을 내는 것입니다. 매수 주문은 가격이 그리드의 하위 노드에 도달할 때, 매도 주문은 가격이 상위 노드에 도달할 때 이루어지며, 이를 통해 시장 변동에서 소액의 수익을 얻을 수 있습니다. 이 전략의 장점은 트레이더가 시장의 방향을 예측할 필요가 없고, 그리드 내의 시장 가격 변동에 의존한다는 것입니다.

그리드 전략 원칙

기존 그리드 거래의 핵심 요소

  • 그리드 노드:매수 또는 매도 주문이 이루어지는 사전 설정된 가격 지점입니다.
  • 그리드 간격:인접한 그리드 노드 간의 가격 거리는 거래를 유발하기 위해 가격이 얼마나 변동해야 하는지를 결정합니다.
  • 그리드 크기:그리드 노드의 총 개수는 전략이 적용되는 가격 범위를 결정합니다.

그리드 트레이딩 전략의 작동 방식

  • 가격이 낮은 수준에서 상승하여 설정된 그리드 노드를 돌파하면 매도 주문이 실행됩니다.
  • 가격이 높은 수준에서 하락하여 설정된 그리드 노드를 돌파하면 매수 주문이 실행됩니다.
  • 다양한 범위 내에서 끊임없이 “낮은 가격에 사고 높은 가격에 파는” 방식을 취하면, 범위 내에서 가격이 왔다 갔다 하더라도 각각의 변동에서 여전히 수익을 낼 수 있습니다.

그리드 전략의 그리드 간격을 8,000달러에서 9,000달러로 설정하고, 그리드 간격을 500달러로 설정했다고 가정해 보겠습니다. 가격이 8,000달러에서 8,500달러로 상승하면, 이 전략은 8,000달러에 매수하고 8,500달러에 매도합니다. 가격이 9,000달러로 더 상승하면, 보유 주식의 일부를 다시 매도합니다. 가격이 9,000달러에서 8,500달러로 하락하면, 다시 매수합니다. 이러한 과정을 반복함으로써, 이 전략은 시장 변동 속에서도 지속적으로 수익을 축적할 수 있습니다.

그리드 트레이딩 전략과 균형 트레이딩 전략의 비교

균형 전략의 핵심은 자산의 고정 비율, 예를 들어 디지털 화폐 50%, 법정화폐 50%를 유지하는 것입니다. 암호화폐 가격이 상승하고 보유 암호화폐의 비중이 50%를 초과하면 매도하고, 가격이 하락하면 매수합니다. 이를 통해 보유 자산의 가치가 고정 비율에 가깝게 유지됩니다. 균형 전략은 시장 변동에 관계없이 일정량의 암호화폐를 유지합니다.

그리드 전략과 균형 전략의 유사점과 차이점

  • 유사점:둘 다 낮은 가격에 사서 높은 가격에 파는 방식으로 변동성을 이용해 수익을 내며, 시장이 원래 가격으로 돌아올 때 가치를 실현할 수 있는 전략입니다.
  • 차이점:그리드 전략은 미리 설정된 가격 범위 내에서만 작동하는 반면, 균형 전략은 특정 가격 범위와 무관합니다. 그리드 전략은 가격이 범위를 벗어나면 거래를 지속할 수 없는 반면, 균형 전략은 유동성을 유지하면서 지속적인 매수 및 매도를 가능하게 합니다.

계약: 산술 그리드 전략

산술격자 전략은 변동성이 큰 시장에서 자주 사용되는 고전적인 양적 거래 전략입니다. 이 전략은 고정된 가격 간격(산술 간격)으로 매수 및 매도 주문을 넣어 가격 변동에서 수익을 얻습니다. 암호화폐나 일부 선물 계약처럼 변동성이 크지만 방향성이 예측 불가능한 시장에 적합합니다.

코어 로직

핵심 개념:

  1. 등거리 간격
    산술격자 전략에서는 매수가와 매도가 사이에 차이가 있습니다.고정 가격 간격, 코드에 있는grid예를 들어, 가격이 300단위 변동할 때(코드처럼)grid=300), 매수 또는 매도 주문이 실행됩니다.

  2. 그리드 초기화
    이 전략은 현재 가격을 기반으로 초기 매수 및 매도 가격을 생성합니다.buyp 그리고 sellp두 가격 간격은 그리드 간격을 기준으로 합니다.grid현재 가격보다 위, 아래로 각각 설정grid단위.

  3. 이익을 실현하고 되돌리기
    가격이 특정 범위까지 상승하면, 이 전략은 롱 포지션 영역에서 매수하고 매도 주문을 설정하여 이익을 실현합니다. 가격이 역 포지션 영역까지 계속 상승하면(upper), 롱 포지션은 이익을 실현하고 숏 포지션을 취하고, 그 반대의 경우도 마찬가지입니다.

  4. 그리드 내 위치 관리
    그리드 내의 각 매수 또는 매도 동작은 가격이 사전 설정된 가격에 도달하면 트리거됩니다.buyp 또는 sellp각 거래가 끝나면 시스템은 자동으로 다음 매수 및 매도 가격 그룹을 조정하여 고정된 그리드 간격을 유지합니다.

  5. 위치 추가 및 축소
    이 전략은 그리드 가격에 따라 포지션을 지속적으로 조정합니다. 가격이 매수 시점에 도달하면 포지션을 늘리고(포지션 증가), 가격이 매도 시점에 도달하면 포지션을 점진적으로 줄입니다(포지션 감소). 반복적인 매수와 매도를 통해 모든 작은 시장 변동을 포착합니다.

전략 코드

'''backtest
start: 2024-08-26 00:00:00
end: 2024-09-25 00:00:00
period: 1m
basePeriod: 1m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT","balance":2500}]
args: [["H",30],["n1",0.001],["grid",300],["bottom",50000]]
'''

# 交易参数配置(设为策略参数)
M = 20          # 杠杆大小
H = 50          # 初始底仓份数
n1 = 1          # 单个网格交易数量
grid = 200      # 单个网格交易间距
bottom = 35000  # 开多点位
upper = 60000   # 开空点位

def CancelPendingOrders():
    orders = _C(exchanges[0].GetOrders)
    if len(orders)>0:
        for j in range(len(orders)):
            exchanges[0].CancelOrder(orders[j].Id, orders[j])
            j=j+1

def main():
    exchange.SetContractType('swap')
    exchange.SetMarginLevel(M)
    currency=exchange.GetCurrency()
    if _G('buyp') and _G('sellp'):
        buyp=_G('buyp')
        sellp=_G('sellp')
        Log('读取网格价格')
    else:
        ticker=exchange.GetTicker()
        buyp=ticker["Last"]-grid
        sellp=ticker["Last"]+grid
        _G('buyp',buyp)
        _G('sellp',sellp)
        Log('网格数据初始化')
    while True:
        account=exchange.GetAccount()
        ticker=exchange.GetTicker()
        position=exchange.GetPosition()
        orders=exchange.GetOrders()
        if len(position)==0:
            if ticker["Last"]>upper:
                exchange.SetDirection('sell')
                exchange.Sell(-1,n1*H)
                Log(currency,'到达开空区域,买入空头底仓')
                
            else:
                exchange.SetDirection('buy')
                exchange.Buy(-1,n1*H)
                Log(currency,'到达开多区域,买入多头底仓')
        if len(position)==1:
            if position[0]["Type"]==1: #持有空头仓位
                if ticker["Last"]<bottom:
                    Log(currency,'空单全部止盈反手')
                    exchange.SetDirection('closesell')
                    exchange.Buy(-1,position[0].Amount)
                else: 
                    orders=exchange.GetOrders()
                    if len(orders)==0: 
                        exchange.SetDirection('sell')
                        exchange.Sell(sellp,n1)
                        exchange.SetDirection('closesell')
                        exchange.Buy(buyp,n1)
                    if len(orders)==1:
                        if orders[0]["Type"]==1: #止盈成交
                            Log(currency,'网格减仓,当前份数:',position[0].Amount)
                            CancelPendingOrders()
                            buyp=buyp-grid
                            sellp=sellp-grid
                            LogProfit(account["Balance"])
                        if orders[0]["Type"]==0:
                            Log(currency,'网格加仓,当前份数:',position[0].Amount)
                            CancelPendingOrders()
                            buyp=buyp+grid
                            sellp=sellp+grid
                            LogProfit(account["Balance"])
        
            if position[0]["Type"]==0:
                if ticker["Last"]>float(upper):
                    Log(currency,'多单全部止盈反手')
                    exchange.SetDirection('closebuy')
                    exchange.Sell(-1,position[0].Amount)
                else:
                    orders=exchange.GetOrders()
                    if len(orders)==0:
                        exchange.SetDirection('buy')
                        exchange.Buy(buyp,n1)
                        exchange.SetDirection('closebuy')
                        exchange.Sell(sellp,n1)
                    if len(orders)==1:
                        if orders[0]["Type"]==0: #止盈成交
                            Log(currency,'网格减仓,当前份数:',position[0].Amount)
                            CancelPendingOrders()
                            buyp=buyp+grid
                            sellp=sellp+grid
                            LogProfit(account["Balance"])
                        if orders[0]["Type"]==1:
                            Log(currency,'网格加仓,当前份数:',position[0].Amount)
                            CancelPendingOrders()
                            buyp=buyp-grid
                            sellp=sellp-grid
                            LogProfit(account["Balance"])

image

산술 격자 전략은 암호화폐 시장, 특히 변동성이 크지만 예측 불가능한 시장에서 상당한 적용 가능성을 제공합니다. 고정된 가격 간격으로 매수 및 매도 주문을 냄으로써, 이 전략은 자동화된 운영과 단순한 논리를 유지하면서도 시장 변동을 효과적으로 포착합니다. 암호화폐 시장의 높은 변동성은 이 전략이 성공할 수 있는 좋은 기회를 제공합니다.

산술 그리드 전략의 거래 비용은 주로 매수 및 매도 주문의 잦은 발생에서 발생하며, 주문 체결이나 취소에는 영향을 미치지 않는다는 점에 유의해야 합니다. 이러한 특성 때문에 거래 수수료가 높은 암호화폐 거래소에 특히 주의해야 합니다. 수익을 최적화하려면 수수료가 낮은 거래소를 선택하고, 특정 시장 상황에 따라 그리드 간격과 펀드 배분 비율을 조정하는 것이 좋습니다.

전반적으로 산술 그리드 전략은 변동성이 큰 암호화폐 시장에 적합하지만, 일방적인 시장에서는 상당한 위험에 노출될 수 있습니다. 매개변수를 적절히 설정하고 자금 관리를 최적화함으로써 전략의 견고성과 수익성을 효과적으로 향상시킬 수 있습니다.

스팟: 다이내믹 그리드 전략

동적 그리드 전략기존의 고정 그리드 전략과 달리동적 생성그리고메시 노드 조정이 전략은 시장 변동에 대한 유연성을 높여줍니다. 실시간 시장 변동에 따라 새로운 그리드 노드를 생성하여 전략의 적응성과 위험 관리 역량을 향상시킵니다. 핵심 개념은 가격 변동이 특정 임계값을 초과할 때만 새로운 노드를 생성하고 포지션을 적절하게 관리하는 것입니다.

핵심 기능

  1. 동적 메시 노드 생성

    • 시장 가격이 이전 그리드 노드를 돌파하고 변동 범위가 사전 설정된 범위를 초과합니다(_GridPointDis제어), 이 전략은 새로운 그리드 노드를 생성합니다.
    • 각 그리드 노드는 현재 가격 및 포지션 정보를 기록하고 마감 조건을 설정합니다(_GridCovDis통제된 마감 스프레드).
  2. 매수 및 매도 작업

    • 긴 방향direction = 1): 가격이 상승하여 그리드 노드를 돌파하면 보유하고 있던 자산을 매도하고, 가격이 떨어지면 다시 매수합니다.
    • 짧은 방향direction = -1): 가격이 하락하여 그리드 노드를 돌파하면 자산을 매수하고, 반등하면 보유한 자산을 매도합니다.
  3. 마감 작업

    • 가격이 설정된 종가에 도달하면 (_GridCovDis현재 방향에 따라 매수(롱 포지션 시) 또는 매도(숏 포지션 시) 작업을 실행하여 포지션 종료를 완료합니다.
  4. 메쉬 수량 제어

    • 그리드 노드의 개수가 최대 설정값을 초과하는 경우(_GridNum), 이 전략은 자동으로 가장 빠른 그리드 노드를 삭제하여 과도한 위치를 방지하고 위험을 줄입니다.

코어 로직

  1. 초기화 매개변수

    • _GridNum: 최대 그리드 노드 수, 제어 전략이 동시에 유지할 수 있는 최대 그리드 노드 수입니다.
    • _GridPointAmount: 각 그리드 노드의 주문 수량.
    • _GridPointDis: 그리드 노드 사이의 가격 간격입니다.
    • _GridCovDis: 포지션을 청산할 때 적용되는 가격 차이입니다. 시장 가격과 그리드 가격의 변동폭이 이 가격 차이를 초과하면 포지션이 청산됩니다.
  2. UpdateGrid 함수

    • 현재 가격을 기준으로 (current_price), 구매 가격 (bids_price) 및 판매 가격(asks_price) 그리드 노드를 업데이트합니다. 시장 가격이 그리드 노드를 돌파할 때마다 전략은 새로운 그리드 노드를 생성하고 해당 거래를 실행합니다.
    • 마감 조건이 발생하는지 확인하고, 발생 시 마감 작업을 실행합니다.
    • 그리드 노드의 최대 개수를 제어합니다. 최대 개수를 초과하면 가장 오래된 그리드 노드가 삭제됩니다.
  3. 메인 루프

    • main이 기능은 지속적으로 실시간 시장 가격 데이터를 수집하고 호출합니다.UpdateGrid함수는 그리드 노드를 업데이트하고 거래 작업을 수행합니다.
    • 통과하다LogStatus전략 운영에 대한 실시간 모니터링을 용이하게 하기 위해 현재 그리드 상태, 계정 정보 등을 기록합니다.

전략 코드(Python spot 및 도면 템플릿 참조 필요)

'''backtest
start: 2024-04-01 00:00:00
end: 2024-09-23 08:00:00
period: 1d
basePeriod: 1d
exchanges: [{"eid":"Binance","currency":"ETH_USDT"}]
'''

direction = 1  # 网格方向:1表示向上,-1表示向下
_GridNum = 10  # 网格节点数量
_GridPointAmount = 0.1  # 每个网格节点的下单量
_GridPointDis = 100  # 网格节点之间的价格间距
_GridCovDis = 150  # 平仓价与网格节点的差距
_Grid = []  # 网格数据列表

def UpdateGrid(nowBidsPrice, nowAsksPrice, direction):  # up 1, down -1
    global _Grid

    # 检查是否需要创建新的网格节点
    if len(_Grid) == 0 or (direction == 1 and nowBidsPrice - _Grid[-1]['price'] > _GridPointDis) or \
            (direction == -1 and _Grid[-1]['price'] - nowAsksPrice > _GridPointDis):
        
        if len(_Grid) == 0:
            Log('策略起始')
        if len(_Grid) != 0 and direction == 1 and nowBidsPrice - _Grid[-1]['price'] > _GridPointDis:
            Log('向上突破,突破阈值:', nowBidsPrice - _Grid[-1]['price'])
        if len(_Grid) != 0 and direction == -1 and _Grid[-1]['price'] - nowAsksPrice > _GridPointDis:
            Log('向下突破,突破阈值:', _Grid[-1]['price'] - nowAsksPrice)

        # 根据方向决定当前网格节点的价格
        nowPrice = nowBidsPrice if direction == 1 else nowAsksPrice
        _Grid.append({
            'price': nowPrice if len(_Grid) == 0 else _Grid[-1]['price'] + _GridPointDis * direction,
            'hold': {'price': 0, 'amount': 0},
            'coverPrice': (nowPrice - direction * _GridCovDis) if len(_Grid) == 0 else _Grid[-1]['price'] + _GridPointDis * direction - direction * _GridCovDis
        })

        Log('网格更新数量:', len(_Grid), '网格最新增添:', _Grid[-1])

        # 下单操作,向上突破时卖出,向下突破时买入
        tradeInfo = ext.Sell(_GridPointAmount) if direction == 1 else ext.Buy(_GridPointAmount)
        _Grid[-1]['hold']['price'] = tradeInfo['price']
        _Grid[-1]['hold']['amount'] = tradeInfo['amount']

        Log('网格操作:', '向上卖出' if direction == 1 else '向下买入')

    # 检查是否需要平仓
    if len(_Grid) > 0 and (
            (direction == 1 and nowAsksPrice < _Grid[-1]['coverPrice']) or 
            (direction == -1 and nowBidsPrice > _Grid[-1]['coverPrice'])):

        coverInfo = ext.Buy(_Grid[-1]['hold']['amount']) if direction == 1 else ext.Sell(_Grid[-1]['hold']['amount'])
        Log('价格跌破平仓价格,买入,去除最后添加网格' if direction == 1 else '价格突破平仓价格,卖出,去除最后添加网格')

        _Grid.pop()  # 移除已平仓的网格节点
    
    # 如果网格数量超出设定值,则平掉最早的网格节点
    elif len(_Grid) > _GridNum:
        coverFirstInfo = ext.Buy(_Grid[0]['hold']['amount']) if direction == 1 else ext.Sell(_Grid[0]['hold']['amount'])
        Log('网格数量过多,买入操作,去除初始网格' if direction == 1 else '网格数量过多,卖出操作,去除初始网格')
        _Grid.pop(0)

def main():
    global _Grid
    while True:
        ticker = _C(exchange.GetTicker)
        records = _C(exchange.GetRecords)
        ext.PlotRecords(records, "kline")
        UpdateGrid(ticker['Buy'], ticker['Sell'], direction)

        # 记录当前网格状态
        msg = ""
        for grid in _Grid:
            msg += str(grid) + "\n"
        
        LogStatus(_D(), _C(exchange.GetAccount), "\n", "_Grid.length:", len(_Grid), "_GridNum:", _GridNum, "\n", msg)
        Sleep(500)

image

참고:

  1. 모든 사람이 그리드 생성 과정을 이해하는 데 도움이 되도록 코드에 많은 주석을 추가했으며, 실제 응용 프로그램에서는 이를 삭제할 수 있습니다.
  2. 현물 전략은 거래를 원활하게 하기 위해 현물 템플릿 거래 라이브러리를 사용합니다. 자세한 내용은 소스 코드를 참조하세요.
  3. 실제 거래에 적용하려면 각 거래소의 특성에 맞게 개선이 필요합니다.

미래: 롱-숏 양방향 그리드 전략

롱-숏 양방향 그리드 전략은 더욱 복잡하지만 강력한 그리드 전략으로, 롱과 숏 방향으로 동시에 거래할 수 있어 변동성이 큰 시장에서 수익 기회를 극대화합니다. 이 전략의 핵심은 초기 가격 대비 가격 변동에 따라 포지션을 동적으로 조정하여 진정한 시장 중립 전략을 구현한다는 것입니다.

핵심 기능

  1. 긴 모드와 짧은 모드 모두: 가격이 오르든 내리든 상관없이 해당 방향으로 운용하면 수익을 얻을 수 있는 전략입니다.
  2. 동적 위치 조정:초기가격 대비 가격편차 비율을 기준으로 목표 포지션을 계산합니다.
  3. 양방향 그리드 순서: 양방향 가격 변동을 포착하기 위해 매수 및 매도 주문을 동시에 설정합니다.
  4. 위험 관리:합리적인 포지션 관리 및 주문 통제를 통해 일방적 리스크 감소

전략 논리

전략의 핵심 논리는 가격과 초기 가격의 편차 정도에 따라 목표 위치를 결정하는 것입니다.

  • 가격이 상승하면 목표 포지션은 마이너스(숏)이고, 가격이 상승할수록 숏 포지션이 커집니다.
  • 가격이 하락하면 목표 포지션은 양수(롱)가 됩니다. 가격이 더 많이 하락할수록 롱 포지션의 비중이 커집니다.
  • 그리드 주문 실행을 통해 실제 위치를 목표 위치로 점진적으로 조정합니다.

전략 코드

import time
import math

# 全局变量初始化
InitPrice = 800
Funding = 50000

# 策略参数(需要在策略页面设置)
pct = 5.0        # 网格间距百分比
value = 5000      # 每个网格的投入金额
Interval = 3     # 策略执行间隔(秒)

# 账户资产信息
assets = {
    'USDT': {
        'total_balance': 0,
        'margin_balance': 0,
        'margin': 0,
        'unrealised_profit': 0
    }
}

def init():
    """初始化策略"""
    global symbol, Funding, base_currency
    
    Log('交易模式:多空都做')
    
    # 设置合约类型
    exchange.SetContractType('swap')
    
    # 获取交易币种
    currency = exchange.GetCurrency()
    symbol = currency  # 保持原格式,如 "BTC_USDT"
    base_currency = symbol.split('_')[0]  # 获取基础币种,如 "BTC"
    Log('交易币种:', symbol)
    Log('基础币种:', base_currency)

    swapcode = symbol + '.swap'
    ticker = exchange.GetTicker(swapcode)  # 回测系统需要
    exchange_info = exchange.GetMarkets()
    data = exchange_info.get(swapcode)
    
    # 初始化资产信息
    assets[base_currency] = {
        'amount': 0,
        'price': 0,
        'hold_price': 0,
        'price': 0,
        'unrealised_profit': 0,
        'leverage': 20,
        'liquidation_price': 0,
        'AmountPrecision': data['AmountPrecision'],
        'PricePrecision': data['PricePrecision'],
        'MinQty': data['MinQty']
    }
    
    # 撤销所有挂单
    cancel_all_orders()
    
    # 获取初始资金
    account = exchange.GetAccount()
    if account:
        Funding = account.Balance + account.FrozenBalance
        Log('初始资金:', Funding)

def calculate_grid_orders():
    """计算网格订单"""
    if InitPrice == 0 or assets[base_currency]['price'] == 0:
        return None
    
    current_price = assets[base_currency]['price']
    current_amount = assets[base_currency]['amount']
    
    # 多空都做模式:根据价格变化计算目标持仓
    price_change_ratio = (current_price - InitPrice) / InitPrice
    target_amount = -price_change_ratio * (value / pct) / current_price
    
    # 计算买卖价格
    grid_spacing = current_price * (pct / 100)  # 网格间距
    buy_price = current_price - grid_spacing
    sell_price = current_price + grid_spacing
    
    # 计算订单数量
    order_amount = value / current_price
    
    return {
        'buy_price': round(buy_price, assets[base_currency]['PricePrecision']),
        'sell_price': round(sell_price, assets[base_currency]['PricePrecision']),
        'buy_amount': round(order_amount, assets[base_currency]['AmountPrecision']),
        'sell_amount': round(order_amount, assets[base_currency]['AmountPrecision']),
        'target_amount': target_amount
    }

def execute_strategy():
    """执行交易策略"""
    # 计算网格订单
    grid_info = calculate_grid_orders()
    if not grid_info:
        return
    
    current_amount = assets[base_currency]['amount']
    target_amount = grid_info['target_amount']
    amount_diff = target_amount - current_amount
    
    # 如果持仓偏离较大,先调整持仓
    if abs(amount_diff) > assets[base_currency]['MinQty']:
        cancel_all_orders()
        Sleep(500)
        
        # 判断需要的操作
        if amount_diff > 0:
            # 需要增加多头持仓或减少空头持仓
            if current_amount >= 0:
                # 当前是多头或空仓,直接开多
                Log(f'当前持仓:{current_amount},需要开多:{abs(amount_diff):.6f}')
                open_position('LONG', assets[base_currency]['price'], abs(amount_diff))
            else:
                # 当前是空头,需要先平空再开多
                if abs(amount_diff) <= abs(current_amount):
                    # 只需要平掉部分空仓
                    Log(f'当前空仓:{current_amount},需要平仓:{abs(amount_diff):.6f}')
                    safe_close_position(abs(amount_diff), assets[base_currency]['price'])
                else:
                    # 需要平掉所有空仓,然后开多
                    Log(f'平掉所有空仓:{abs(current_amount):.6f}')
                    if safe_close_position(abs(current_amount), assets[base_currency]['price']):
                        Sleep(1000)  # 等待平仓完成
                        
                        # 更新持仓信息
                        update_account()
                        remaining_amount = abs(amount_diff) - abs(current_amount)
                        if remaining_amount > assets[base_currency]['MinQty']:
                            Log(f'开多剩余数量:{remaining_amount:.6f}')
                            open_position('LONG', assets[base_currency]['price'], remaining_amount)
        
        elif amount_diff < 0:
            # 需要增加空头持仓或减少多头持仓
            if current_amount <= 0:
                # 当前是空头或空仓,直接开空
                Log(f'当前持仓:{current_amount},需要开空:{abs(amount_diff):.6f}')
                open_position('SHORT', assets[base_currency]['price'], abs(amount_diff))
            else:
                # 当前是多头,需要先平多再开空
                if abs(amount_diff) <= current_amount:
                    # 只需要平掉部分多仓
                    Log(f'当前多仓:{current_amount},需要平仓:{abs(amount_diff):.6f}')
                    safe_close_position(abs(amount_diff), assets[base_currency]['price'])
                else:
                    # 需要平掉所有多仓,然后开空
                    Log(f'平掉所有多仓:{current_amount:.6f}')
                    if safe_close_position(current_amount, assets[base_currency]['price']):
                        Sleep(1000)  # 等待平仓完成
                        
                        # 更新持仓信息
                        update_account()
                        remaining_amount = abs(amount_diff) - current_amount
                        if remaining_amount > assets[base_currency]['MinQty']:
                            Log(f'开空剩余数量:{remaining_amount:.6f}')
                            open_position('SHORT', assets[base_currency]['price'], remaining_amount)
    
    # 检查是否需要重新挂网格单
    orders = exchange.GetOrders()
    if not orders or len(orders) < 2:  # 多空都做模式需要2个订单
        cancel_all_orders()
        Sleep(500)
        
        # 重新获取最新持仓信息
        update_account()
        current_amount = assets[base_currency]['amount']
        
        # 挂买单和卖单(网格订单)
        buy_amount = grid_info['buy_amount']
        sell_amount = grid_info['sell_amount']
        
        # 多空都做模式:无论当前持仓如何,都要挂多空双向网格单
        place_grid_orders(current_amount, grid_info, buy_amount, sell_amount)

def place_grid_orders(current_amount, grid_info, buy_amount, sell_amount):
    """放置网格订单 - 多空都做模式"""
    Log(f'放置网格订单 - 当前持仓:{current_amount}')
    
    # 多空都做模式:无论当前持仓如何,都要挂多空双向网格单
    Log(f'多空都做模式 - 挂开多单:数量={buy_amount:.6f},价格={grid_info["buy_price"]}')
    open_position('LONG', grid_info['buy_price'], buy_amount)
    Sleep(200)
    Log(f'多空都做模式 - 挂开空单:数量={sell_amount:.6f},价格={grid_info["sell_price"]}')
    open_position('SHORT', grid_info['sell_price'], sell_amount)

def cancel_all_orders():
    """撤销所有未成交订单"""
    try:
        orders = exchange.GetOrders()
        if orders:
            for order in orders:
                exchange.CancelOrder(order['Id'])
                Sleep(100)  # 避免频繁操作
        return True
    except Exception as e:
        Log('撤单异常:', str(e))
        return False

def get_real_position():
    """获取真实持仓信息"""
    try:
        positions = exchange.GetPosition()
        if positions:
            for pos in positions:
                if pos['ContractType'] == 'swap' and pos['Amount'] > 0:
                    position_amount = pos['Amount'] * (1 if pos['Type'] == 0 else -1)
                    return position_amount, pos['Price'], pos['Profit']

        return 0, 0, 0
    except Exception as e:
        Log('获取持仓异常:', str(e))
        return 0, 0, 0

def update_account():
    """更新账户信息"""
    try:
        account = exchange.GetAccount()
        if not account:
            Log('获取账户信息失败')
            return False
        
        # 更新USDT资产信息
        assets['USDT']['total_balance'] = account.Balance + account.FrozenBalance
        assets['USDT']['margin_balance'] = account.Balance
        
        # 获取真实持仓信息
        position_amount, hold_price, profit = get_real_position()
        assets[base_currency]['amount'] = position_amount
        assets[base_currency]['hold_price'] = hold_price
        assets[base_currency]['unrealised_profit'] = profit
        
        return True
    except Exception as e:
        Log('更新账户异常:', str(e))
        return False

def update_price():
    """更新行情价格"""
    global InitPrice
    
    ticker = exchange.GetTicker()
    if not ticker:
        Log('获取行情失败')
        return False
    
    # 设置初始价格
    if InitPrice == 0:
        InitPrice = ticker.Last
        Log('设置初始价格:', InitPrice)
    
    assets[base_currency]['price'] = ticker.Last
    return True

def create_order(side, price, amount, order_type="开仓"):
    """使用CreateOrder下单函数"""
    try:
        if amount <= 0:
            Log(f'订单数量无效:{amount}')
            return False
        
        # 构造期货合约symbol
        contract_symbol = f"{symbol}.swap"
        
        # 下单
        order_id = exchange.CreateOrder(contract_symbol, side, price, amount)
        
        if order_id:
            Log(f'{order_type} {side} 下单成功:价格={price}, 数量={amount}, 订单ID={order_id}')
            return order_id
        else:
            Log(f'{order_type} {side} 下单失败:价格={price}, 数量={amount}')
            return False
            
    except Exception as e:
        Log('下单异常:', str(e))
        return False

def safe_close_position(close_amount, price=-1):
    """安全平仓函数"""
    try:
        if close_amount <= 0:
            Log(f'平仓数量无效:{close_amount}')
            return False
        
        # 实时获取持仓信息
        current_position, _, _ = get_real_position()
        
        # 检查是否真的有持仓
        if current_position == 0:
            Log('当前无持仓,跳过平仓操作')
            return False
        
        # 检查平仓数量是否超过持仓
        if abs(close_amount) > abs(current_position):
            Log(f'平仓数量超过持仓:持仓{current_position},平仓{close_amount},调整为持仓数量')
            close_amount = abs(current_position)
        
        # 根据当前持仓方向确定平仓操作
        if current_position > 0:  # 当前是多仓
            side = "closebuy"  # 平多仓
            Log(f'平多仓:数量={close_amount},价格={price}')
        else:  # 当前是空仓
            side = "closesell"  # 平空仓
            Log(f'平空仓:数量={close_amount},价格={price}')
        
        return create_order(side, price, close_amount, "平仓")
        
    except Exception as e:
        Log('平仓异常:', str(e))
        return False

def open_position(direction, price, amount):
    """开仓函数"""
    try:
        if amount <= 0:
            Log(f'开仓数量无效:{amount}')
            return False
        
        # 确定开仓方向
        if direction == 'LONG':
            side = "buy"  # 开多仓
            Log(f'开多仓:数量={amount},价格={price}')
        else:  # SHORT
            side = "sell"  # 开空仓
            Log(f'开空仓:数量={amount},价格={price}')
        
        return create_order(side, price, amount, "开仓")
        
    except Exception as e:
        Log('开仓异常:', str(e))
        return False

def update_status():
    """更新状态显示"""
    try:
        if Funding > 0:
            current_balance = assets['USDT']['total_balance']
            profit = current_balance - Funding
            profit_rate = (profit / Funding) * 100
            
            status_info = f"""
策略状态 - {symbol}
交易模式: 多空都做
当前价格: {assets[base_currency]['price']}
初始价格: {InitPrice}
持仓数量: {assets[base_currency]['amount']}
持仓价格: {assets[base_currency]['hold_price']}
账户余额: {current_balance:.4f} USDT
总收益: {profit:.4f} USDT ({profit_rate:.2f}%)
未实现盈亏: {assets[base_currency]['unrealised_profit']:.4f} USDT
"""
            LogStatus(status_info)
    
    except Exception as e:
        Log('状态更新异常:', str(e))

def main():
    """主函数"""
    # 设置错误过滤
    SetErrorFilter("502:|503:|tcp|character|unexpected|network|timeout|WSARecv|Connect|GetAddr|no such|reset|http|received|EOF|reused|Unknown")
    
    # 初始化
    init()
    
    Log('策略启动成功')
    
    while True:
        try:
            # 更新账户信息
            if not update_account():
                Log('更新账户信息失败,等待重试')
                Sleep(5000)
                continue
            
            # 更新价格信息
            if not update_price():
                Log('更新价格信息失败,等待重试')
                Sleep(5000)
                continue
            
            # 执行策略
            execute_strategy()
            
            # 更新状态
            update_status()
            
            # 休眠
            Sleep(Interval * 1000)
            
        except Exception as e:
            Log('主循环异常:', str(e))
            Sleep(5000)  # 发生异常时等待5秒再继续

디지털 화폐 분야의 여러 그리드 전략에 대한 간략한 논의

롱숏 투웨이 그리드 전략의 장점은 다양한 시장 상황에 적응할 수 있다는 점입니다. 상승, 하락, 또는 변동성 여부에 관계없이 적절한 운용을 통해 수익성 있는 수익을 창출할 수 있습니다. 하지만 특히 극단적인 시장 상황에서는 신중한 위험 관리가 필요합니다.

요약하다

그리드 전략은 유연성과 자동화 덕분에 양적 거래에서 널리 사용되는 도구입니다. 다양한 그리드 변형은 다양한 시장 환경에 적응할 수 있으며, 각 전략은 고유한 적용 시나리오와 장점을 가지고 있습니다. 투자자는 특정 시장 변동성과 개인의 위험 감수 성향에 따라 적절한 그리드 전략을 선택하고, 동적 포지션 관리, 손절매 및 이익실현 전략과 같은 도구와 결합하여 전략의 효율성을 더욱 최적화할 수 있습니다.

필요설명하다이 글에서 다루는 세 가지 전략은 모두 Inventor 플랫폼의 Strategy Plaza에서 제공하는 요약본입니다. 고전적인 양적 전략 유형인 그리드 전략은 마진 콜을 피하고 위험을 완화하는 방법, 수익률 향상을 위해 자금 활용을 최적화하는 방법 등 여전히 탐구할 만한 가치가 많습니다. 관심 있는 분은 Strategy Plaza를 방문하여 실시간 그리드 전략을 참고하고 연구해 보세요.