4
Подписаться
1271
Подписчики

Использование ИИ для обратного обучения разработке стратегий: новый способ улучшения навыков количественной торговли

Создано: 2025-04-27 10:14:30, Обновлено: 2025-04-27 13:34:44
comments   2
hits   933

[TOC]

Использование ИИ для обратного обучения разработке стратегий: новый способ улучшения навыков количественной торговли

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

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

Лично я считаю, что существуют две основные причины текущих проблем со стратегиями прямого вывода ИИ:

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

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

Используя преимущества ИИ, ИИ может относительно точно понимать анализ конкретного кода, поскольку для ИИ данные кода представляют собой «1 есть 1, 2 есть 2», и не будет никакой логической путаницы, двусмысленности или других проблем, вызванных требованиями описания естественного языка. Так почему бы не использовать преимущества ИИ, чтобы сократить объем ручной работы и в полной мере раскрыть преимущества ручного труда?

Как использовать ИИ для обратного обучения стратегиям?

Его можно разделить на следующие этапы:

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

  • Пусть ИИ поможет нам объяснить стратегию

Понять общую идею

Разберите функциональные модули каждой части.

Уточните используемые индикаторы, параметры и торговую логику.

  • Задайте дополнительные вопросы, чтобы помочь ИИ проанализировать плюсы и минусы стратегии.

В каких рыночных условиях стратегия работает лучше?

Каковы возможные точки риска?

Какие области можно оптимизировать и улучшить?

  • Проверьте и скорректируйте на основе собственных размышлений

Тестирование на исторических данных по разным продуктам и периодам

Добавьте дополнительные фильтры или меры контроля рисков

Наблюдайте за изменениями в производительности и формируйте собственные идеи

Упражняться

Давайте позволим ИИ изучить стратегию и объяснить ее нам, чтобы увидеть, соответствует ли она нашим ожиданиям. Это может помочь нам научиться количественной оценке.

Образец политики

Разработка и реализация пошаговой торговой стратегии увеличения позиции на основе фильтрации тренда EMA Адрес стратегии: https://www.fmz.com/strategy/492116

/*backtest
start: 2024-10-01 00:00:00
end: 2025-04-23 00:00:00
period: 1h
basePeriod: 1m
exchanges: [{"eid":"Futures_Binance","currency":"ETH_USDT"}]
args: [["targetProfit",20],["amount",20],["amountPrecision",3],["isAmountForUSDT",true]]
*/

function getTotalEquity_OKEX_V5() {
    var totalEquity = null 
    var ret = exchange.IO("api", "GET", "/api/v5/account/balance", "ccy=USDT")
    if (ret) {
        try {
            totalEquity = parseFloat(ret.data[0].details[0].eq)
        } catch(e) {
            Log("获取账户总权益失败!")
            return null
        }
    }
    return totalEquity
}

function getTotalEquity_Binance() {
    var totalEquity = null 
    var ret = exchange.GetAccount()
    if (ret) {
        try {
            totalEquity = parseFloat(ret.Info.totalWalletBalance)
        } catch(e) {
            Log("获取账户总权益失败!")
            return null
        }
    }
    return totalEquity
}

function getTotalEquity() {
    var exName = exchange.GetName()
    if (exName == "Futures_OKCoin") {
        return getTotalEquity_OKEX_V5()
    } else if (exName == "Futures_Binance") {
        return getTotalEquity_Binance()
    } else {
        throw "不支持该交易所"
    }
}

function ceilToDecimals(value, decimals) {
    const factor = Math.pow(10, decimals);
    return Math.ceil(value * factor) / factor;
}

function cancelAll() {
    while (1) {
        var orders = _C(exchange.GetOrders)
        if (orders.length == 0) {
            break
        }
        for (var i = 0 ; i < orders.length ; i++) {
            exchange.CancelOrder(orders[i].Id, orders[i])
            Sleep(interval)
        }
        Sleep(interval)
    }
}

function trade(distance, price, amount) {
    var tradeFunc = null 
    if (distance == "buy") {
        tradeFunc = exchange.Buy
    } else if (distance == "sell") {
        tradeFunc = exchange.Sell
    } else if (distance == "closebuy") {
        tradeFunc = exchange.Sell
    } else {
        tradeFunc = exchange.Buy
    }
    exchange.SetDirection(distance)
    return tradeFunc(price, amount)
}

function openLong(price, amount) {
    return trade("buy", price, amount)
}

function openShort(price, amount) {
    return trade("sell", price, amount)
}

function coverLong(price, amount) {
    return trade("closebuy", price, amount)
}

function coverShort(price, amount) {
    return trade("closesell", price, amount)
}

function plotRecords(c, buyOrder, sellOrder, pos) {
    var bars = _C(exchange.GetRecords)
    if (bars.length == 0) {
        return  
    }

    bars.forEach(function(bar, index) {
        c.begin(bar)
        if (index == bars.length - 1) {
            if (buyOrder) {
                c.hline(buyOrder.Price, "buy", "rgba(255, 0, 0, 0.2)", "dotted")
            }
            if (sellOrder) {
                c.hline(sellOrder.Price, "sell", "rgba(0, 255, 0, 0.2)", "dotted")
            }
            if (pos && pos.length == 1) {
                c.hline(pos[0].Price, "pos", "rgba(0, 0, 255, 0.2)", "dashed")
            }
        }
        c.close()
    })
}

var buyOrderId = null
var sellOrderId = null
var logStatusMsgBuff = ""

function main() {
    var exName = exchange.GetName()    
    if (isSimulate && exName == "Futures_OKCoin") {
        exchange.IO("simulate", true)
    }

    if (isReset) {
        _G(null)
        LogReset(1)
        LogProfitReset()
        LogVacuum()
        Log("重置所有数据", "#FF0000")
    }

    exchange.SetContractType(contractType)
    exchange.SetPrecision(pricePrecision, amountPrecision)
    Log("设置精度", pricePrecision, amountPrecision)
    exchange.SetMarginLevel(marginLevel)

    if (totalEq == -1 && !IsVirtual()) {
        var recoverTotalEq = _G("totalEq")
        if (!recoverTotalEq) {
            var currTotalEq = getTotalEquity()
            if (currTotalEq) {
                totalEq = currTotalEq
                _G("totalEq", currTotalEq)
            } else {
                throw "获取初始权益失败"
            }
        } else {
            totalEq = recoverTotalEq
        }
    }

    var addCounter = _G("addCounter")
    if (!addCounter) {
        addCounter = 1
        if (setAddCounter != -1) {
            addCounter = setAddCounter
        }
        _G("addCounter", addCounter)
    } else {
        addCounter -= 1
    }

    let c = KLineChart({
        overlay: true
    })
    
    var isLock = false 
    while (true) {
        var ticker = _C(exchange.GetTicker)        
        var pos = _C(exchange.GetPosition)
        if (pos.length > 1) {
            Log(pos)
            throw "同时有多空持仓"
        }

        var r = _C(exchange.GetRecords, 60 * 60)
        var ema = TA.EMA(r, 60)
        if (Math.abs(ticker.Last - ema[ema.length - 2]) / ema[ema.length - 2] > 0.03) {
            cancelAll()
            isLock = true 
        }
        if (Math.abs(ticker.Last - ema[ema.length - 2]) / ema[ema.length - 2] < 0.02) {
            isLock = false 
        }
        if (isLock) {
            LogStatus(_D(), "暂停, 检测阈值:", _N(Math.abs(ticker.Last - ema[ema.length - 2]) / ema[ema.length - 2], 3), logStatusMsgBuff)
            plotRecords(c, null, null, pos)
            Sleep(interval)
            continue 
        }

        var currentAcc = _C(exchange.GetAccount)
        if (currentAcc.Balance < totalEq * reserve) {
            throw "no money, stop"
        }

        if (addCounter > maxAddCounter) {
            LogStatus(_D(), "加仓已达到上限", logStatusMsgBuff)
            if (isMaxAddCounterClear && pos.length >= 1) {
                Log("加仓已达到上限,撤单,清仓")
                cancelAll()
                if (pos[0].Type == PD_LONG) {
                    var coverId = coverLong(-1, pos[0].Amount)
                } else if (pos[0].Type == PD_SHORT) {
                    var coverId = coverShort(-1, pos[0].Amount)
                }
                addCounter = 1
            }
            continue
        }

        if (pos.length == 0) {
            if (!IsVirtual()) {
                var currTotalEq = getTotalEquity()
                if (currTotalEq) {
                    LogProfit(currTotalEq - totalEq, "当前总权益:", currTotalEq)
                }
            }

            var tradeAmountLong = amount
            var tradeAmountShort = amount
            if (isAmountForUSDT) {
                tradeAmountLong = ceilToDecimals(tradeAmountLong * 1.01 / (ticker.Last - targetProfit / 5) / oneCtValue, amountPrecision)
                tradeAmountShort = ceilToDecimals(tradeAmountShort * 1.01 / (ticker.Last + targetProfit / 5) / oneCtValue, amountPrecision)
            }

            buyOrderId = openLong(ticker.Last - targetProfit / 5, tradeAmountLong)
            sellOrderId = openShort(ticker.Last + targetProfit / 5, tradeAmountShort)

            addCounter = 1
            _G("addCounter", addCounter)
        } else if (pos[0].Type == PD_LONG) {
            var n = ratio
            var price = ticker.Last
            var addAmount = isDoubling ? pos[0].Amount : (isAmountForUSDT ? (ceilToDecimals(amount * 1.01 / (price - targetProfit * n) / oneCtValue, amountPrecision)) : amount)
            buyOrderId = openLong(price - targetProfit * n, addAmount)
            sellOrderId = coverLong(pos[0].Price + targetProfit, pos[0].Amount)

            addCounter++
            _G("addCounter", addCounter)
        } else if (pos[0].Type == PD_SHORT) {
            var n = ratio
            var price = ticker.Last
            var addAmount = isDoubling ? pos[0].Amount : (isAmountForUSDT ? (ceilToDecimals(amount * 1.01 / (price + targetProfit * n) / oneCtValue, amountPrecision)) : amount)
            buyOrderId = coverShort(pos[0].Price - targetProfit, pos[0].Amount)
            sellOrderId = openShort(price + targetProfit * n, addAmount)

            addCounter++
            _G("addCounter", addCounter)
        }

        if (!sellOrderId || !buyOrderId) {
            cancelAll()
            buyOrderId = null 
            sellOrderId = null
            continue
        } 

        while (1) { 
            var isFindBuyId = false 
            var isFindSellId = false
            var orders = _C(exchange.GetOrders)
            var buyOrder = null 
            var sellOrder = null 
            for (var i = 0 ; i < orders.length ; i++) {
                if (buyOrderId == orders[i].Id) {
                    isFindBuyId = true 
                    buyOrder = orders[i]
                }
                if (sellOrderId == orders[i].Id) {
                    isFindSellId = true 
                    sellOrder = orders[i]
                }               
            }
            if (!isFindSellId && !isFindBuyId) {    
                cancelAll()
                break
            } else if (!isFindBuyId) {   
                Log("买单成交")
                cancelAll()
                break
            } else if (!isFindSellId) {  
                Log("卖单成交")
                cancelAll()
                break
            }

            var acc = _C(exchange.GetAccount)
            var tbl = {"type": "table", "title": "data", "cols": ["data", "symbol", "type", "price", "amount"], "rows": []}
            if (buyOrder) {
                tbl.rows.push(["订单", buyOrder.Symbol, buyOrder.Type == ORDER_TYPE_BUY ? "买入" : "卖出", buyOrder.Price, buyOrder.Amount])
            }
            if (sellOrder) {
                tbl.rows.push(["订单", sellOrder.Symbol, sellOrder.Type == ORDER_TYPE_BUY ? "买入" : "卖出", sellOrder.Price, sellOrder.Amount])
            }
            if (pos && pos.length == 1) {
                tbl.rows.push(["持仓", pos[0].Symbol, pos[0].Type == PD_LONG ? "多" : "空", pos[0].Price, pos[0].Amount])
            }

            logStatusMsgBuff = "当前权益:" + acc.Equity + ", 初始权益:" + totalEq + (!IsVirtual() ? ", 浮动盈亏:" + (acc.Equity - totalEq) : "") + ", 加仓次数:" + addCounter + "\n`" + JSON.stringify(tbl) + "`"
            LogStatus(_D(), "当前权益:", acc.Equity, ", 初始权益:", totalEq, !IsVirtual() ? ", 浮动盈亏:" + (acc.Equity - totalEq) : "", ", 加仓次数:" + addCounter, "\n`" + JSON.stringify(tbl) + "`")

            plotRecords(c, buyOrder, sellOrder, pos)            
            Sleep(interval)
        }
        Sleep(interval)
    }
}

function onexit() {
    Log("扫尾,撤销所有挂单")
    cancelAll()
}

Для новых пользователей платформы FMZ вид такой кучи кодов может вызвать чувство растерянности. Вместо того чтобы изучать код строка за строкой, мы могли бы (проявить ленивость) и передать его ИИ, позволить ИИ объяснить нам и повысить эффективность обучения.

Объяснение ИИ

Здесь я использую GPT, и следующий контент объясняется с помощью искусственного интеллекта:

  • Обзор В этой статье будет представлена ​​пошаговая торговая стратегия увеличения позиции, основанная на фильтрации тренда EMA (экспоненциальной скользящей средней). Эта стратегия в основном используется на Binance Futures (Futures_Binance), поддерживает 1-часовое бэктестирование и основана на 1-минутной агрегации данных K-line. Отслеживая в режиме реального времени отклонение между ценой и EMA, стратегия динамически переключает режимы торговли (обычная торговля/приостановленная торговля), постепенно увеличивает позиции на стабильном рынке и автоматически приостанавливает позиции при аномальных колебаниях, чтобы избежать рисков.

    1. Логика стратегии
      1. Фильтрация тренда (управление положением замка) Рассчитайте 60-периодную EMA по данным свечей последнего часа. При отклонении текущей цены от EMA более чем на 3% приостановите размещение ордеров и отмените отложенные ордера. Когда отклонение снова достигнет 2%, нормальная торговля возобновится. Благодаря фильтрации трендов вы можете избежать риска ликвидации, вызванного частым увеличением позиций в условиях нестабильного рынка.
      1. Логика добавления позиций (постепенное добавление позиций) Если изначально позиции нет, одновременно выставляются два отложенных ордера: ордер на покупку по низкой цене и ордер на продажу по высокой цене. Цена заказа: Ордер на покупку размещается ниже текущей цены (расстояние targetProfit/5) Ордер на продажу размещается выше текущей цены (расстояние targetProfit/5) В случае исполнения отложенного ордера будет произведено пошаговое увеличение позиции: Если ордер на покупку исполнен, продолжайте размещать следующий ордер на покупку по более низкой цене и устанавливайте стоп-приказ на продажу для существующей позиции. Если ордер на продажу исполнен, продолжайте размещать следующий ордер на продажу по более высокой цене и устанавливайте стоп-приказ на покупку для существующей позиции. Количество добавляемых позиций может быть установлено в двойном или фиксированном размере. Когда количество добавлений позиций достигает maxAddCounter, стратегия может выбрать принудительную ликвидацию.
      1. Контроль позиций и защита капитала Установите размер каждой открытой позиции на основе начального общего капитала (totalEq). Поддержка оценки количества контрактов по сумме USDT (автоматический расчет объема заказа на основе базовой цены). Убедитесь, что остаток средств на счете превышает определенную долю (резерв). Если баланс недостаточен, прекратите торговлю.
    1. Введение в основные функции и модули
      1. Получить общий баланс счета Функция getTotalEquity инкапсулирована для Binance Futures (Futures_Binance) и OKEX V5 (Futures_OKCoin). Совместимость с различиями API различных бирж, единообразный возврат текущих общих активов счета (номинированных в USDT).
      1. Модуль размещения и отмены заказов торговля(направление, цена, сумма): инкапсулирует унифицированный интерфейс ордера. cancelAll(): Отменить все отложенные ордера, чтобы предотвратить накопление риска из-за слишком большого количества отложенных ордеров.
      1. Открытие длинных, открытие коротких и закрытие позиций openLong(цена, сумма): открыть длинную позицию. openShort(цена, сумма): открыть короткую позицию. coverLong(цена, количество): близко к длинному. coverShort(цена, количество): пусто.
      1. Количество добавленных позиций и записей о статусе Использование_G() постоянно записывает количество добавлений позиций addCounter, чтобы избежать потери статуса добавления позиций после отключения и перезапуска. Используйте LogStatus для динамического отображения информации о счете в реальном времени, статуса отложенных заказов и информации о позициях.
      1. Чертеж диаграммы Используйте KLineChart для рисования ключевых линий, таких как цена ордера на покупку, цена ордера на продажу, средняя цена позиции и т. д., для визуального тестирования и мониторинга в режиме реального времени.
    1. Схема стратегии
  flowchart TD
      开始 --> 初始化参数
      初始化参数 --> 账户余额检查
      账户余额检查 --> 计算EMA
      计算EMA --> 判断是否锁仓
      判断是否锁仓 -->|是| 暂停交易
      判断是否锁仓 -->|否| 正常交易
      正常交易 --> 是否有持仓
      是否有持仓 -->|无| 首次挂单
      是否有持仓 -->|有| 按持仓方向加仓与止盈挂单
      首次挂单 --> 等待成交
      按持仓方向加仓与止盈挂单 --> 等待成交
      等待成交 --> 挂单成交检测
      挂单成交检测 --> 成交后调整
      成交后调整 --> 更新加仓次数
      更新加仓次数 --> 是否超出最大加仓次数
      是否超出最大加仓次数 -->|是| 平仓
      是否超出最大加仓次数 -->|否| 继续交易
  • Пятое: резюме Эта пошаговая стратегия увеличения позиции на основе фильтрации EMA учитывает как доходность, так и контроль рисков и подходит для работы на волатильном и слабоволатильном рынке. Благодаря гибким методам добавления позиций и механизмам приостановки тренда можно эффективно снизить вероятность ликвидации и повысить эффективность использования капитала. Он поддерживает как бэктестинг, так и реальную торговлю, а его модульная конструкция позволяет легко расширять его. Например, он может дополнительно ввести динамическую корректировку targetProfit и суммы или добавить другие технические индикаторы для усиления эффекта фильтрации.

    • Хотите, чтобы я дал вам более продвинутое предложение? например: Как улучшить двухстороннюю позицию (двусторонняя позиция) Как динамически регулировать коэффициент увеличения позиции Как внедрить логику стоп-лосса для контроля рисков?

Местные вопросы/объяснения

Относительно вопросов GPT:

Использование ИИ для обратного обучения разработке стратегий: новый способ улучшения навыков количественной торговли

Следующий контент поясняется ИИ:

В этой стратегии фильтрация тенденций достигается за счет:

var ema = TA.EMA(r, 60)
if (Math.abs(ticker.Last - ema[ema.length - 2]) / ema[ema.length - 2] > 0.03) {
    cancelAll()
    isLock = true 
}
if (Math.abs(ticker.Last - ema[ema.length - 2]) / ema[ema.length - 2] < 0.02) {
    isLock = false 
}
if (isLock) {
    LogStatus(_D(), "暂停, 检测阈值:", _N(Math.abs(ticker.Last - ema[ema.length - 2]) / ema[ema.length - 2], 3), logStatusMsgBuff)
    plotRecords(c, null, null, pos)
    Sleep(interval)
    continue 
}
  • Анализ кода Фильтр тренда EMA: TA.EMA(r, 60) используется для расчета экспоненциальной скользящей средней (EMA) за последние 60 часов. r — исторические данные K-линии, полученные с помощью exchange.GetRecords, а каждая точка данных представляет собой один час ценовой информации. Массив EMA хранит значение EMA для каждого часа.[ema.length - 2] представляет значение EMA предыдущего часа в текущий момент времени.

Блокировка и снятие тренда: Сравнивая разницу между текущей ценой (ticker.Last) и значением EMA предыдущего часа, вычисляется процент отклонения цены от EMA. Math.abs(ticker.Last - ema[ema.length - 2]) / ema[ema.length - 2] вычисляет процентное отклонение текущей цены от EMA предыдущего часа. Если отклонение превышает 3% (> 0,03), то считается, что рыночная тенденция существенно изменилась, и вызывается функция cancelAll() для отмены всех отложенных ордеров, а isLock устанавливается в значение true, т. е. позиция блокируется, предотвращая дальнейшую торговлю. Если цена отклоняется от EMA менее чем на 2% (< 0,02), состояние блокировки снимается и isLock устанавливается в значение false.

Приостановка торговли: Если isLock имеет значение true (что указывает на то, что позиция в данный момент заблокирована), никакие дальнейшие торговые операции выполняться не будут. Программа выведет записи журнала и вызовет plotRecords() для построения диаграммы, показывающей текущую тенденцию и статус положения. Используйте Sleep(interval), чтобы сделать паузу на определенный период времени, а затем продолжить цикл.

  • Бэктестинг

Использование ИИ для обратного обучения разработке стратегий: новый способ улучшения навыков количественной торговли

Кажется, некоторые тенденции можно отфильтровать. Прочитав код самостоятельно, я обнаружил, что объяснение ИИ было очень понятным, даже более понятным, чем если бы я объяснял его сам.

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

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

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

  • Глубокое обучение. Существующие стратегии
  • Быстро понимать сложную логику
  • Систематический опыт проектирования
  • Постоянная оптимизация и инновации

Только этот путь может по-настоящему расширить наши возможности количественной торговли и создать нашу собственную систематическую торговую систему. На платформе количественной торговли Inventor мы можем в полной мере использовать возможности искусственного интеллекта и объединить его с собственной практикой, чтобы двигаться дальше и летать выше.