2
Suivre
319
Abonnés

Cadre de stratégie quantitative multidevises Python : idées de conception et mise en œuvre détaillées

Créé le: 2025-08-29 13:10:54, Mis à jour le: 2025-08-31 09:11:53
comments   0
hits   626

introduction:

Récemment, un utilisateur de Xiaocao TeacherComment créer rapidement une stratégie de trading multidevises universelle après la mise à niveau FMZN’hésitez pas à laisser un commentaire dans la section « Commentaires » de cet article, dans l’espoir de proposer une implémentation Python de ce framework stratégique. Pour répondre aux besoins des développeurs Python, cet article s’appuie sur les idées originales de Xiaocao et les combine avec l’environnement de trading simulé de Binance pour expliquer en détail comment créer un framework universel de trading quantitatif multidevises.

Ce framework présente les caractéristiques suivantes :

  • Basé sur le langage Python, facile à comprendre et à développer
  • Prise en charge des transactions simultanées multidevises
  • Utilisation de l’échange simulé Binance pour les tests de sécurité
  • Fournit des exemples de code complets et des commentaires détaillés

Nous espérons que cet article vous aidera à démarrer rapidement avec le trading quantitatif multidevises. Nous invitons également les développeurs à innover et à optimiser leurs stratégies en s’appuyant sur cette expérience pour créer des stratégies de trading encore plus complètes et personnalisées. Continuons à explorer ensemble la voie du trading quantitatif !

Stratégie d’initialisation

Dans la phase d’initialisation de la stratégie de trading, nous définissons d’abord les variables globalesSYMBOLSQUOTOINTERVAL, représente la devise de transaction cible, la devise de base et l’intervalle de temps,InfoLes variables sont utilisées pour stocker toutes les données clés requises pendant le fonctionnement de la stratégie.InitInfoLa fonction initialise ces données, y compris les informations de compte, la gestion du temps, les données de marché pour chaque devise de trading, les informations de commande, les informations de position, etc. Ces étapes d’initialisation garantissent que la stratégie a une structure de données claire et un état initial lorsqu’elle est en cours d’exécution, jetant les bases de l’exécution ultérieure de la stratégie.

import time
import json 

SYMBOLS = 'LINK,ETH,TRB'
QUOTO = 'USDT'
INTERVAL = 5

# 全局变量,储存数据
# SYMBOLS代表要交易的币种,格式如"BTC,ETH,LTC"
# QUOTO为基础货币,永续合约常见的有USDT,USDC
# INTERVAL代表循环的间隔
Info = {
    'trade_symbols': SYMBOLS.split(','),  # 交易币种
    'base_coin': QUOTO,                   # 基础货币
    'ticker': {},                         # 行情数据
    'order': {},                          # 订单信息
    'account': {},                        # 账户信息
    'precision': {},                      # 精度信息
    'position': {},                       # 仓位信息
    'time': {},                           # 时间相关数据
    'count': {},                          # 计数器
    'interval': INTERVAL                  # 循环的间隔时间
}

# 初始化策略
def InitInfo():

    # 初始化账户信息,初始余额为0
    Info['account'] = {
        'init_balance': 0,  # 初始余额
        'wallet_balance': 0,  # 钱包余额
        'margin_balance': 0,  # 保证金余额
        'margin_used': 0,  # 已用保证金
        'margin_free': 0,  # 可用保证金
        'profit': 0,  # 总收益
        'profit_rate': 0,  # 收益率
        'unrealised_profit': 0,  # 未实现收益
    }

    # 初始化时间数据,控制更新的时间
    Info['time'] = {
        'update_ticker_time': 0,    # 更新行情的时间
        'update_pos_time': 0,       # 更新仓位的时间
        'update_profit_time': 0,    # 更新利润的时间
        'update_account_time': 0,   # 更新账户信息的时间
        'update_status_time': 0,    # 更新状态的时间
        'last_loop_time': 0,        # 上一次主循环的时间
        'loop_delay': 0,             # 循环延迟
        'start_time': time.time()
    }

    # 初始化每个交易币种的数据
    for symbol in Info['trade_symbols']:
        Info['ticker'][symbol] = {'last': 0, 'ask': 0, 'bid': 0}  # 行情
        Info['order'][symbol] = {                                 # 订单信息
            'buy': {'id': 0, 'price': 0, 'amount': 0},
            'sell': {'id': 0, 'price': 0, 'amount': 0}
        }
        Info['position'][symbol] = {                              # 仓位信息
            'amount': 0, 'hold_price': 0, 'unrealised_profit': 0, 'open_time': 0, 'value': 0
        }
        Info['precision'][symbol] = {}  # 精度信息初始化为空
        Info['position'][symbol] = {                              # 仓位信息
            'amount': 0, 'hold_price': 0, 'unrealised_profit': 0, 'open_time': 0, 'value': 0
        }

Obtenir des informations sur le marché et des paramètres de précision

Cette étape garantit que l’exactitude des prix, des quantités et des autres aspects des devises que nous traitons, ainsi que la quantité commandée, sont conformes aux normes de la plateforme. Les exigences minimales de précision pour les prix et les quantités varient selon les paires de trading (comme BTC/USD ou ETH/USDT). Nous devons donc obtenir ces informations de précision auprès de l’API de la plateforme pour éviter les ordres non conformes. Par exemple, ETH/USDT peut autoriser deux décimales, tandis que BTC/USDT peut en autoriser huit.

Le but:

  • Obtenez l’exactitude du prix et de la quantité pour chaque devise afin de garantir l’exactitude des données de commande.
  • Évitez les échecs de commande dus à des erreurs de précision.
# 获取精度信息
def GetPrecision():
    # 获取交易所的市场信息
    for presym in Info['trade_symbols']:
        curcontract = presym + '_USDT.swap'
        exchange.GetTicker(curcontract)
    exchange_info = exchange.GetMarkets()
    
    # 遍历市场中的所有交易对
    for pair, data in exchange_info.items():
        symbol = pair.split('_')[0]  # 永续合约交易对的格式为 BTC_USDT.swap
        
        # 检查该交易对是否为我们要交易的币种,基础货币是否匹配,且是永续合约
        if symbol in Info['trade_symbols'] and pair.split('.')[0].endswith(Info['base_coin']) and pair.endswith('swap'):
            # 获取该交易对的精度信息
            Info['precision'][symbol] = {
                'tick_size': data['TickSize'],                  # 价格精度
                'amount_size': data['AmountSize'],              # 数量精度
                'price_precision': data['PricePrecision'],      # 价格小数位精度
                'amount_precision': data['AmountPrecision'],    # 数量小数位精度
                'min_qty': data['MinQty'],                      # 最小下单数量
                'max_qty': data['MaxQty'],                      # 最大下单数量
                'min_notional': data['MinNotional'],            # 最小交易额
                'ctVal': data['CtVal']                          # 合约价值,如1张代表0.01个币
            }
            
            # 检查合约价值的计价货币是否为symbol,避免币本位情况
            if data['CtValCcy'] != symbol:
                raise Exception("不支持币本位")

GetPrecisionfonction

  • Obtenez des informations sur le marché auprès des bourses via des API, y compris des paramètres de précision pour les paires de trading.
  • Pour les paires de trading éligibles, enregistrez des informations telles que la précision du prix, la précision de la quantité, les volumes de transaction minimum et maximum et la valeur du contrat.
  • Vérifie s’il s’agit d’une transaction à marge de pièces et génère une exception si tel est le cas.

Obtenir des devis

Accédez aux données de marché actuelles via l’API, telles que le dernier cours, le meilleur cours acheteur, le meilleur cours vendeur et la profondeur du carnet d’ordres. Ces informations sont cruciales pour les décisions de trading ultérieures. Selon la stratégie, ces données peuvent être basées sur des graphiques en chandeliers (données OHLC) ou des données tick-by-tick.

Le but:

  • Obtenez les dernières données de trading du marché actuel afin que la stratégie puisse prendre des décisions d’achat et de vente sur la base de ces données.
  • Contient l’acquisition de données en temps réel et historiques pour les calculs d’indicateurs techniques.
# 更新行情信息
def UpdateTicker():
    
    # 记录当前更新时间戳
    Info['time']['update_ticker_time'] = time.time() * 1000 # 使用time.time()获取当前时间的时间戳
    
    # 遍历获取到的行情数据
    for ticpre in Info['trade_symbols']:
        
        curcontract = ticpre + '_' + QUOTO + '.swap'
        data = exchange.GetTicker(curcontract)
        
        if not data:
            Log("获取行情失败", GetLastError())
            return
        # 提取交易币种,永续合约格式如 'BTC_USDT.swap',这里取币种名 'BTC'
        symbol = data['Symbol'].split('_')[0]
        
        # 过滤掉不是基础货币(Info['base_coin'])的交易对或不是永续合约的交易对
        if not data['Symbol'].split('.')[0].endswith(Info['base_coin']) or symbol not in Info['trade_symbols'] or not data['Symbol'].endswith('swap'):
            continue
        
        # 更新行情的卖出价、买入价和最后成交价
        Info['ticker'][symbol]['ask'] = float(data['Sell'])  # 卖出价
        Info['ticker'][symbol]['bid'] = float(data['Buy'])   # 买入价
        Info['ticker'][symbol]['last'] = float(data['Last']) # 最后成交价
  1. Obtenir des données de marché

    • utiliserexchange.GetTickersObtenez des informations de marché en temps réel pour toutes les paires de trading.tickerLa variable stocke toutes les informations sur les paires de transactions.
  2. Gestion des erreurs

    • Si les données du marché ne peuvent pas être obtenues avec succès, le programme passeLogJournaux et sorties de fonctionsGetLastErrorLe message d’erreur est revenu.
  3. Heure de mise à jour

    • utilisertime.timePour enregistrer l’horodatage de l’heure actuelle, qui est utilisé pour marquer l’heure à laquelle le marché est mis à jour.
  4. Filtrage des données

    • Extraire le nom de la devise de trading à partir des données du marché.
    • Filtrez les paires de trading qui ne répondent pas aux exigences, telles que les paires de trading qui ne sont pas réglées dans la devise de base ou les paires de trading qui ne sont pas des contrats perpétuels.
  5. Mettre à jour les données du marché

    • Pour les devises de trading éligibles, mettez à jour leur prix d’achat, leur prix de vente et leur dernier prix négocié.

Grâce à cette fonction, le système peut obtenir et mettre à jour les dernières informations du marché de la devise de trading cible en temps réel.

Obtenir des informations sur la position du compte

Utilisez l’API pour récupérer le solde de votre compte et vos avoirs actuels (devise, quantité, coût, etc.). Cette étape est essentielle pour évaluer les fonds disponibles, calculer le risque et gérer les positions. Par exemple, vos avoirs actuels détermineront l’augmentation ou la diminution de votre position.

Le but:

  • Assurez-vous qu’il y a suffisamment de fonds ou de positions ouvertes sur votre compte pour exécuter la transaction.
  • Déterminez la taille et la direction de la transaction en fonction de la position actuelle et des fonds du compte.
# 更新账户信息
def UpdateAccount():
   
    # 如果上次更新时间距现在不到1分钟,直接返回
    if time.time() - Info['time']['update_account_time'] < 60:
        return
    
    # 记录账户信息更新时间
    Info['time']['update_account_time'] = time.time() * 1000
    
    # 获取账户信息
    account = exchange.GetAccount()
    
    # 如果账户信息获取失败,记录日志并返回
    if account is None:
        Log("更新账户失败")
        return
    
    # 计算账户信息
    Info['account']['margin_used'] = round(account['Equity'] - account['Balance'], 2)  # 使用的保证金
    Info['account']['margin_balance'] = round(account['Equity'], 2)  # 当前账户余额
    Info['account']['margin_free'] = round(account['Balance'], 2)  # 可用余额
    Info['account']['wallet_balance'] = round(account['Equity'] - account['UPnL'], 2)  # 钱包余额
    Info['account']['unrealised_profit'] = round(account['UPnL'], 2)  # 未实现盈亏

    # 初始化账户初始余额
    if not Info['account']['init_balance']:
        if _G("init_balance") and _G("init_balance") > 0:
            Info['account']['init_balance'] = round(_G("init_balance"), 2)
        else:
            Info['account']['init_balance'] = Info['account']['margin_balance']
            _G("init_balance", Info['account']['init_balance'])
    
    # 计算账户利润及利润率
    Info['account']['profit'] = round(Info['account']['margin_balance'] - Info['account']['init_balance'], 2)
    Info['account']['profit_rate'] = round((100 * Info['account']['profit']) / Info['account']['init_balance'], 2)

    # 计算仓位总价值和杠杆率
    Info['count']['total'] = round(Info['count']['long'] + Info['count']['short'], 2)
    Info['count']['leverage'] = round(Info['count']['total'] / Info['account']['margin_balance'], 2)


# 更新仓位信息
def UpdatePosition():
    
    # 获取永续合约的仓位信息
    pos = exchange.GetPositions(Info['base_coin'] + ".swap")
    
    # 记录仓位信息更新时间
    Info['time']['update_pos_time'] = time.time() * 1000

    # 初始化仓位信息
    position_info = {symbol: {'amount': 0, 'hold_price': 0, 'unrealised_profit': 0} for symbol in Info['trade_symbols']}

    # 遍历仓位信息,更新相应币种的仓位
    for data in pos:
        symbol = data['Symbol'].split("_")[0]
        
        # 过滤掉不符合条件的币种
        if not data['Symbol'].split(".")[0].endswith(Info['base_coin']) or symbol not in Info['trade_symbols']:
            continue
        
        # 如果仓位不为零,则需要单向持仓
        if position_info[symbol]['amount'] != 0:
            raise Exception("需要单向持仓")
        
        # 更新仓位信息
        position_info[symbol] = {
            'amount': data['Amount'] * Info['precision'][symbol]['ctVal'] if data['Type'] == 0 else -data['Amount'] * Info['precision'][symbol]['ctVal'],
            'hold_price': data['Price'],
            'unrealised_profit': data['Profit']
        }

    # 初始化仓位统计数据
    Info['count'] = {'long': 0, 'short': 0, 'total': 0, 'leverage': 0}

    # 遍历更新后的仓位信息
    for symbol, info in position_info.items():
        deal_volume = abs(info['amount'] - Info['position'][symbol]['amount'])
        direction = 1 if info['amount'] - Info['position'][symbol]['amount'] > 0 else -1
        
        # 如果仓位发生变化,记录成交信息
        if deal_volume:
            deal_price = Info['order'][symbol]['buy']['price'] if direction == 1 else Info['order'][symbol]['sell']['price']
            Log(
                symbol,
                "仓位更新:",
                round(Info['position'][symbol]['value'], 1),
                " -> ",
                round(info['amount'] * Info['ticker'][symbol]['last'], 1),
                ", 买" if direction == 1 else ", 卖",
                ", 成交价:",
                deal_price,
                ", 成本价:",
                round(Info['position'][symbol]['hold_price'], Info['precision'][symbol]['price_precision']),
            )

        # 更新仓位信息
        Info['position'][symbol]['amount'] = info['amount']
        Info['position'][symbol]['hold_price'] = info['hold_price']
        Info['position'][symbol]['value'] = round(Info['position'][symbol]['amount'] * Info['ticker'][symbol]['last'], 2)
        Info['position'][symbol]['unrealised_profit'] = info['unrealised_profit']

        # 统计多头和空头仓位价值
        if Info['position'][symbol]['amount'] > 0:
            Info['count']['long'] += abs(Info['position'][symbol]['value'])
        else:
            Info['count']['short'] += abs(Info['position'][symbol]['value'])
  1. UpdateAccountfonction

    • Intervalle de vérification:Chaque fois que vous mettez à jour votre compte, assurez-vous que la dernière mise à jour date de plus d’une minute pour éviter de mettre à jour trop fréquemment.
    • Mettre à jour les informations du compte: Appelexchange.GetAccountObtenez des informations sur votre compte et calculez divers paramètres de compte, tels quemargin_usedwallet_balanceunrealised_profitattendez.
    • Initialiser le solde: Initialiser le solde initial du compte lors de sa première exécution et l’enregistrer dans la variable globaleInfo['account']['init_balance']milieu.
    • Calcul des bénéfices:Calcule le bénéfice et la marge bénéficiaire en fonction du solde actuel et du solde initial.
  2. UpdatePositionfonction

    • Obtenir des informations sur la position: Appelexchange.GetPositions()Obtenez le statut actuel de la position.
    • Mettre à jour la position: Mettre à jour les informations de position de la devise cible en fonction des données de position acquises (telles queamounthold_priceunrealised_profitattendez).
    • Calcul de l’effet de levierCalcule le ratio de levier global en fonction des valeurs actuelles des positions longues et courtes et du solde de marge.

Grâce à ces deux fonctions, la stratégie peut surveiller en permanence l’état du compte et les changements de position, fournissant ainsi un support de données en temps réel pour les décisions de trading ultérieures.

commerce

Exécutez des ordres d’achat ou de vente selon la logique de la stratégie. Il peut s’agir d’ordres au marché, d’ordres à cours limité ou d’autres types d’ordres. Cette étape implique l’interaction avec l’API de la bourse pour envoyer des demandes d’achat ou de vente. L’exécution réussie d’un ordre affecte le solde du compte et l’intérêt ouvert.

Le but:

  • Émettez des instructions de trading via l’API pour effectuer des opérations d’achat et de vente.
  • Assurez-vous que le type et la quantité de commande sont conformes aux exigences de la stratégie et aux réglementations boursières.
# 订单函数
def Order(symbol, direction, price, amount, msg):
    pair = f"{symbol}_{Info['base_coin']}.swap"  # 构造交易对名称
    ret = exchange.CreateOrder(pair, direction, price, amount, msg)  # 执行下单操作
    
    # 判断是否下单成功
    if ret:
        Info['order'][symbol][direction]['id'] = ret  # 记录订单ID
        Info['order'][symbol][direction]['price'] = price  # 记录下单价格
    else:
        Log(f"{symbol} {direction} {price} {amount} 下单异常")  # 输出异常信息

# 交易函数
def Trade(symbol, direction, price, amount, msg):
    
    # 根据最小价格变动调整价格
    price = round(price - (price % Info['precision'][symbol]['tick_size']), Info['precision'][symbol]['price_precision'])
    
    # 计算调整后的交易数量
    amount = amount / Info['precision'][symbol]['ctVal']  # 计算真实合约数量
    amount = round(amount - (amount % Info['precision'][symbol]['amount_size']), Info['precision'][symbol]['amount_precision'])

    # 限制最大交易数量
    if Info['precision'][symbol]['max_qty'] > 0:
        amount = min(amount, Info['precision'][symbol]['max_qty'])
    
    new_order = False
    
    # 如果新价格与之前的订单价格差异大于0.0001,则重新下单

    if Info['order'][symbol][direction]['price'] > 0 and abs(price - Info['order'][symbol][direction]['price']) / price > 0.0001:
        Log('已持订单,订单价格发生变化')
        new_order = True
    
    # 如果交易数量为0或者当前订单ID为0,则撤单
    if amount <= 0 or Info['order'][symbol][direction]['id'] == 0:
        Log('新订单产生')
        new_order = True
    
    # 如果需要新订单
    if new_order:
        # 如果有原有订单,撤销它
        if Info['order'][symbol][direction]['id'] != 0:
            exchange.CancelOrder(Info['order'][symbol][direction]['id'])
            Info['order'][symbol][direction]['id'] = 0
            Info['order'][symbol][direction]['price'] = 0
            Log('撤单成功:', symbol)
        
        
        # 如果更新仓位或ticker的延迟太高,则不下单
        if (time.time() * 1000 - Info['time']['update_pos_time'] > 2 * Info['interval'] * 1000 or 
            time.time() * 1000 - Info['time']['update_ticker_time'] > 2 * Info['interval'] * 1000):
            Log(time.time() * 1000, Info['time']['update_pos_time'], time.time() * 1000 - Info['time']['update_pos_time'])
            Log(time.time() * 1000, Info['time']['update_ticker_time'], time.time() * 1000 - Info['time']['update_ticker_time'])
            Log('延迟过高')
            return
        
        # 如果订单金额或数量过低,不执行下单操作
        if price * amount <= Info['precision'][symbol]['min_notional'] or amount < Info['precision'][symbol]['min_qty']:
            Log(f"{symbol} 下单量太低", price * amount)
            return
        
        # 执行下单操作
        Log('order下单:', symbol)
        Order(symbol, direction, price, amount, msg)
  1. Orderfonction

    • Crée une commande. En cas de succès, l’identifiant et le prix sont enregistrés. En cas d’échec, un message d’erreur s’affiche.
  2. Tradefonction

    • Ajustez en fonction du prix du marché et de la quantité pour déterminer s’il faut annuler la commande et en passer une nouvelle pour éviter les erreurs d’exécution de commande ou les opérations répétées.
  3. CancelOrderfonction

    • Il s’agit d’une opération d’annulation de commande personnalisée, chargée d’annuler la commande en attente en cours.

Affichage de l’état

L’état de fonctionnement de la stratégie est affiché en temps réel, y compris le solde du compte, les positions actuelles, l’état d’exécution des transactions, le prix actuel du marché, etc. Cette étape ne sert pas seulement à surveiller le fonctionnement de la stratégie, mais également à comprendre rapidement les performances de la stratégie lors de l’optimisation et du débogage de la stratégie.

Le but:

  • Affichez les informations clés du fonctionnement de la stratégie en temps opportun pour faciliter la surveillance des utilisateurs.
  • Fournit un mécanisme de rétroaction pour montrer si la transaction a été exécutée avec succès ou s’il y a eu des erreurs.
# 更新状态函数
def UpdateStatus():
    
    # 如果距离上次更新的时间小于4秒,则直接返回
    if time.time() * 1000 - Info['time']['update_status_time'] < 4000:
        return
    
    # 更新状态时间
    Info['time']['update_status_time'] = time.time() * 1000

    # 账户信息表格
    table1 = {
        "type": "table",
        "title": "账户信息",
        "cols": [
            "初始余额", "钱包余额", "保证金余额", "已用保证金", "可用保证金",
            "总收益", "收益率", "未实现收益", "总持仓", "已用杠杆", "循环延时"
        ],
        "rows": [
            [
                Info['account']['init_balance'],  # 初始余额
                Info['account']['wallet_balance'],  # 钱包余额
                Info['account']['margin_balance'],  # 保证金余额
                Info['account']['margin_used'],  # 已用保证金
                Info['account']['margin_free'],  # 可用保证金
                Info['account']['profit'],  # 总收益
                str(Info['account']['profit_rate']) + "%",  # 收益率
                round(Info['account']['unrealised_profit'], 2),  # 未实现收益
                round(Info['count']['total'], 2),  # 总持仓
                Info['count']['leverage'],  # 已用杠杆
                str(Info['time']['loop_delay']) + "ms",  # 循环延时
            ],
        ],
    }
    
    # 交易对信息表格
    table2 = {
        "type": "table",
        "title": "交易对信息",
        "cols": [
            "币种", "方向", "数量", "持仓价格", "持仓价值", 
            "现价", "挂单买价", "挂单卖价", "未实现盈亏"
        ],
        "rows": [],
    }

    # 遍历每个交易对,填充交易对信息
    for symbol in Info['trade_symbols']:
        table2['rows'].append([
            symbol,  # 币种
            "LONG" if Info['position'][symbol]['amount'] > 0 else "SHORT",  # 方向
            round(Info['position'][symbol]['amount'], Info['precision'][symbol]['amount_precision'] + 2),  # 数量
            round(Info['position'][symbol]['hold_price'], Info['precision'][symbol]['price_precision']),  # 持仓价格
            round(Info['position'][symbol]['value'], 2),  # 持仓价值
            round(Info['ticker'][symbol]['last'], Info['precision'][symbol]['price_precision']),  # 现价
            Info['order'][symbol]['buy']['price'],  # 挂单买价
            Info['order'][symbol]['sell']['price'],  # 挂单卖价
            round(Info['position'][symbol]['unrealised_profit'], 2),  # 未实现盈亏
        ])

    # 输出状态日志
    LogStatus(
        f"初始化时间: {time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(Info['time']['start_time']))}\n",
        f"`{json.dumps(table1)}`\n" + f"`{json.dumps(table2)}`\n",
        f"最后执行时间: {time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())}\n"
    )

    # 每10秒钟更新一次账户信息
    if time.time() * 1000 - Info['time']['update_profit_time'] > 10 * 1000:
        UpdateAccount()  # 更新账户信息
        LogProfit(round(Info['account']['profit'], 3), '&')  # 输出收益日志
        Info['time']['update_profit_time'] = time.time() * 1000  # 更新收益时间

Logique de transaction

Le processus décisionnel de base du trading. Sur la base des données de marché, des informations de compte et des positions, combinées à des indicateurs techniques ou des modèles quantitatifs, les décisions d’achat, de vente, d’augmentation ou de réduction des positions sont prises. La logique de trading varie selon la stratégie, comme le suivi de tendance, le retour à la moyenne ou les stratégies de cassure.

Le but:

  • Prenez des décisions de trading intelligentes en fonction des données du marché et de l’état du compte.
  • Gérer diverses situations de marché et s’assurer que les stratégies peuvent fonctionner raisonnablement dans différents environnements de marché.

Pour démontrer l’applicabilité du cadre, la stratégie de trading présentée dans cet article utilise une logique simple. Chaque ordre est fixé à 50 USDT et, lors de son exécution, le montant d’achat ou de vente correspondant est calculé en fonction des cours acheteur et vendeur actuels du marché. Les règles d’exécution de cette stratégie sont très simples et visent à illustrer l’application du cadre stratégique de trading de contrats à terme multidevises dans un environnement de trading réel. Pour garantir simplicité et opérabilité, une condition d’arrêt est définie : lorsque la valeur totale de l’intérêt ouvert d’une paire de trading atteint 2 000 USDT, les ordres suivants cessent. Cela nous permet de démontrer facilement la structure de base de la stratégie et la manière dont le cadre interagit avec les données de marché des bourses.

def MakeOrder():
    
    # 遍历所有交易对
    for symbol in Info['trade_symbols']:
        
        # 获取买价(挂单买价)
        buy_price = Info['ticker'][symbol]['bid']
        
        # 计算买入数量,根据买入金额除以买价
        buy_amount = 50 / buy_price

        # 获取卖价(挂单卖价)
        sell_price = Info['ticker'][symbol]['ask']
        
        # 计算买入数量,根据买入金额除以买价
        sell_amount = 50 / sell_price

        
        # 如果当前持仓的总价值小于2000,则进行买入操作
        if Info['position'][symbol]['value'] < 2000:
            Log('进入交易')
            Log('设定价格:', Info['ticker'][symbol]['bid'])
            Trade(symbol, "buy", buy_price, buy_amount, symbol)  # 执行买入操作
        
        #if Info['position'][symbol]['value'] < 3000:
        #    Trade(symbol, "sell", sell_price, sell_amount, symbol)  # 执行买入操作

Boucle principale

La boucle principale est au cœur du cadre stratégique et assure la performance constante et stable de la stratégie sur le marché. Elle effectue régulièrement diverses opérations à intervalles réguliers, telles que l’obtention des dernières données de marché, la mise à jour des informations de position et l’exécution des décisions de trading. Grâce à elle, la stratégie peut réagir en temps réel aux fluctuations du marché et garantir que chaque exécution est basée sur les données de marché les plus récentes. Généralement, la boucle principale est déclenchée une fois par période (par exemple, toutes les minutes, toutes les heures ou lors de la génération d’un nouveau chandelier).

Le but:

  • Assurer le fonctionnement continu et stable de la stratégie, obtenir des données de marché en temps réel et prendre des décisions de trading.
  • Chaque cycle garantit l’exécution en temps réel et précise de la stratégie.
def OnTick():
    try:
        # 更新市场行情信息
        UpdateTicker()
        # 更新持仓信息
        UpdatePosition()
        # 执行下单操作
        MakeOrder()
        # 更新状态信息
        UpdateStatus()
    except Exception as error:
        # 记录循环中发生的错误
        Log("循环出错: " + str(error))

def main():
    LogReset(0)  
    apiBase = "https://testnet.binancefuture.com"  # 币安期货仿真交易所        
    exchange.SetBase(apiBase)  # 设置仿真交易所基站
    # 初始化信息
    exchange.IO('dual', False)  # 单向持仓
    InitInfo()
    GetPrecision()
    
    while True:  # 无限循环
        loop_start_time = time.time() * 1000  # 获取当前时间(毫秒)
        
        # 检查上次循环时间与设定的间隔时间是否已过
        if time.time() * 1000 - Info['time']['last_loop_time'] > Info['interval'] * 1000:
            OnTick()  # 调用 OnTick 函数
            
            # 更新最后一次循环时间
            Info['time']['last_loop_time'] = time.time() * 1000
            # 计算当前循环的延迟时间
            Info['time']['loop_delay'] = time.time() * 1000 - loop_start_time
        
        # 暂停5毫秒,避免过度消耗CPU资源
        Sleep(5000)

Explication du code :

  1. OnTickfonctionCette fonction est la tâche principale exécutée à chaque étape de la boucle principale. Elle est responsable de la mise à jour des informations de marché et de position, de l’exécution des transactions et de la mise à jour du statut de la stratégie. Toutes les mises à jour des transactions et des informations sont effectuées via cette fonction. Toute erreur d’exécution est enregistrée et journalisée.

  2. mainfonctionLa fonction principale initialise les informations pertinentes, configure la station de base d’échange et démarre une boucle infinie. À chaque boucle, le programme vérifie si l’intervalle de temps défini est écoulé. Si c’est le cas,OnTickLa fonction sera appelée pour exécuter la stratégie. Si l’intervalle de temps n’est pas encore écoulé, le programme attendra et poursuivra la boucle pour s’assurer que la stratégie est exécutée conformément à l’intervalle de temps prédéterminé.

  3. Contrôle du retardAprès chaque boucle, le programme marque une pause de 5 millisecondes pour réduire la charge du processeur. Cela permet d’éviter une consommation excessive de ressources de calcul due aux boucles à haute fréquence.

Logique de fonctionnement

  • Phase d’initialisation: Définissez d’abord l’API et les autres paramètres nécessaires, puis initialisez les informations et obtenez la précision de la devise.
  • Phase de la boucle principale:Entrez une boucle infinie, chaque boucle vérifiera l’intervalle de temps pour s’assurer que l’intervalle de temps pour l’exécution de la politique correspond aux paramètres prédéfinis.
  • Phase d’exécution:Une fois la condition d’intervalle de temps remplie,OnTickLa fonction sera appelée pour effectuer toutes les opérations de stratégie, y compris les mises à jour des informations de marché, l’exécution des transactions, etc.

Cette conception de boucle principale garantit que la stratégie continue de fonctionner dans des conditions de marché en temps réel et prend des décisions de trading en temps opportun, améliorant ainsi la stabilité et la précision de la stratégie.

Résumer

Ce cadre stratégique est conçu dans un souci de modularité et d’évolutivité. Chaque étape est clairement définie, garantissant la robustesse tout en facilitant l’expansion et l’optimisation futures. L’exploitation des API d’échange permet de rationaliser les stratégies et de les rendre plus cohérentes grâce aux backtests et au trading en temps réel.

besoinAvisNotez que ce cadre de démonstration utilise la plateforme d’échange simulée Binance comme exemple, afin de fournir un cadre de base pour le développement et le fonctionnement de la stratégie. En pratique, une optimisation basée sur la logique de la stratégie réelle sera nécessaire, notamment l’ajustement dynamique des paramètres en fonction des conditions de marché, l’optimisation des mécanismes de contrôle des risques et l’ajout d’une gestion des exceptions. De plus, en raison des différences d’interfaces API, de règles de trading, de paramètres de précision et de structures tarifaires entre les plateformes, une optimisation et une adaptation détaillées, basées sur les exigences spécifiques de la plateforme cible, seront nécessaires lors de la mise en œuvre réelle afin de garantir la stabilité et la compatibilité de la stratégie. Il est recommandé de tester et de vérifier intégralement la fiabilité et les performances de votre stratégie avant de la déployer en situation réelle.

appendiceAdresse du framework multidevises Python