2
Подписаться
319
Подписчики

Краткое обсуждение нескольких стратегий в области цифровых валют.

Создано: 2025-08-15 16:13:33, Обновлено: 2025-08-26 10:30:15
comments   0
hits   660

Рынок криптовалют предлагает уникальную торговую среду, создавая идеальные условия для применения стратегий грид-трейдинга. В отличие от традиционных финансовых рынков, сектор криптовалют работает круглосуточно, с постоянными и частыми колебаниями цен, что создает обширные возможности для арбитража при использовании грид-стратегий. Более того, основные торговые инструменты, такие как спотовые и бессрочные контракты, не имеют ограничений по сроку действия, что позволяет трейдерам удерживать позиции в долгосрочной перспективе, не беспокоясь о риске истечения срока действия контракта. Кроме того, высокая волатильность и относительно высокая ликвидность рынка криптовалют создают благоприятные условия для реализации грид-стратегий.

Именно благодаря этим характеристикам стратегии грид-трейдинга демонстрируют высокую применимость и потенциальную прибыль на рынке криптовалют. Грид-трейдинг — широко используемая стратегия на рынке криптовалют, позволяющая трейдерам получать прибыль от волатильности рынка без необходимости предсказывать его направление. Размещая ордера на покупку и продажу в разных ценовых диапазонах, грид-трейдинг помогает трейдерам получать прибыль как при росте, так и при падении цен.

Стратегии торговли по сетке имеют множество разновидностей. В этой статье мы кратко рассмотрим несколько форматов, которые помогут новичкам освоить этот классический метод количественной торговли. Основная идея стратегии торговли по сетке заключается в размещении серии ордеров на покупку и продажу на разных ценовых уровнях. Ордера на покупку размещаются, когда цена достигает нижних узлов сетки, а ордера на продажу — когда цена достигает верхних узлов, что позволяет получать небольшую прибыль от рыночных колебаний. Преимущество этой стратегии заключается в том, что трейдерам не нужно предсказывать направление рынка; они полагаются на колебания рыночных цен внутри сетки.

Принципы стратегии сетки

Ключевые элементы традиционной сетевой торговли

  • Узлы сетки:Заранее заданные ценовые точки, по которым размещаются ордера на покупку или продажу.
  • Интервал сетки:Расстояние в цене между соседними узлами сетки определяет, насколько должна измениться цена, чтобы инициировать транзакцию.
  • Размер сетки:Общее количество узлов сетки определяет диапазон цен, охватываемый стратегией.

Как работают стратегии сетевой торговли

  • Когда цена поднимается от низкого уровня и пробивает установленный узел сетки, срабатывает ордер на продажу.
  • Когда цена падает с высокого уровня и пробивает установленный узел сетки, срабатывает ордер на покупку.
  • Постоянно «покупая дешево и продавая дорого» в разных диапазонах, даже если цена колеблется туда-сюда в пределах диапазона, вы все равно можете получать прибыль от каждого колебания.

Пример

Предположим, задана сеточная стратегия с шагом от 8000 до 9000 долларов США и шагом 500 долларов США. При росте цены с 8000 до 8500 долларов США стратегия будет покупать по 8000 долларов США и продавать по 8500 долларов США. Если цена поднимется до 9000 долларов США, стратегия снова продаст часть своих активов. При падении цены с 9000 до 8500 долларов США стратегия снова купит. Повторяя этот процесс, стратегия может непрерывно накапливать прибыль на фоне рыночных колебаний.

Сравнение стратегии сетевой торговли и сбалансированной торговой стратегии

Основой сбалансированной стратегии является поддержание фиксированного соотношения активов, например, 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

Стратегия арифметической сетки широко применима на рынке криптовалют, особенно на волатильных и непредсказуемых рынках. Размещая ордера на покупку и продажу с фиксированными ценовыми интервалами, эта стратегия эффективно отражает рыночные колебания, сохраняя при этом автоматизацию операций и простую логику. Высокая волатильность рынка криптовалют создаёт хорошие возможности для процветания этой стратегии.

Стоит отметить, что транзакционные издержки стратегии арифметической сетки обусловлены в первую очередь частыми ордерами на покупку и продажу, а не их размещением или отменой. Эта особенность требует особого внимания на криптовалютных биржах с высокими комиссиями за транзакции. Для оптимизации доходности рекомендуется выбирать биржи с более низкими комиссиями и корректировать интервал сетки и коэффициент распределения средств в зависимости от конкретных рыночных условий.

В целом, стратегия арифметической сетки хорошо подходит для волатильного рынка криптовалют, но может быть подвержена значительным рискам на односторонних рынках. Правильная настройка параметров и оптимизация управления фондами позволяют существенно повысить надежность и прибыльность стратегии.

Spot: Стратегия динамической сетки

Стратегия динамической сеткиВ отличие от традиционной стратегии фиксированной сетки, онаДинамическая генерацияиНастройка узлов сеткиЭта стратегия обеспечивает большую гибкость при колебаниях рынка. Она генерирует новые узлы сетки на основе рыночных колебаний в режиме реального времени, повышая адаптивность стратегии и возможности контроля рисков. Основная концепция заключается в создании новых узлов только при превышении ценовыми колебаниями определённого порога и соответствующем управлении позициями.

Основные характеристики

  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. Применительно к реальной торговле его необходимо совершенствовать в соответствии с особенностями различных бирж.

Фьючерсы: стратегия двунаправленной сетки с длинной и короткой позицией

Стратегия «Двунаправленная сетка» (Long-Short Bidirection Grid) — это более сложный, но мощный вариант сетки, позволяющий одновременно торговать как в длинных, так и в коротких направлениях, максимизируя возможности получения прибыли на волатильных рынках. Суть этой стратегии заключается в динамической корректировке позиций в зависимости от отклонения цены от начальной, что позволяет достичь по-настоящему рыночно-нейтральной стратегии.

Основные характеристики

  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秒再继续

Краткое обсуждение нескольких стратегий в области цифровых валют.

Преимущество стратегии «длинные-короткие» с двусторонним сеточным графиком заключается в её адаптивности к различным рыночным условиям, что позволяет получать прибыль за счёт соответствующих операций, будь то рост, падение или волатильность. Однако она также требует тщательного управления рисками, особенно в экстремальных рыночных условиях.

Подвести итог

Гибкость и автоматизация сеточных стратегий делают их распространённым инструментом в количественной торговле. Различные варианты сеточных стратегий адаптируются к различным рыночным условиям. Каждая стратегия имеет свои специфические сценарии применения и преимущества. Инвесторы могут выбрать подходящую сеточную стратегию, исходя из конкретных рыночных колебаний и собственной склонности к риску, и комбинировать её с такими инструментами, как динамическое управление позициями и стратегии стоп-лосса и тейк-профита, для дальнейшей оптимизации эффективности стратегии.

нуждатьсяпроиллюстрироватьВсе три стратегии, обсуждаемые в этой статье, взяты из раздела Strategy Plaza на платформе Inventor и содержат краткое описание. Будучи классическим типом количественной стратегии, сеточные стратегии по-прежнему предлагают много интересного для изучения, например, как избежать маржин-коллов и снизить риск, а также как оптимизировать использование средств для повышения доходности. Заинтересованные лица могут посетить раздел Strategy Plaza, где для ознакомления и изучения доступны сеточные стратегии в режиме реального времени.