В процессе загрузки ресурсов... загрузка...

Комбинированная маркетинговая стратегия MACD-KDJ

Автор:Чао Чжан, Дата: 2024-12-05 16:35:26
Тэги:MACDKDJSMA

 MACD-KDJ Combined Martingale Pyramiding Quantitative Trading Strategy

Обзор

Эта стратегия представляет собой торговую систему Мартингейла, основанную на индикаторах MACD и KDJ, сочетающую в себе размещение позиций в виде пирамиды и динамическое управление прибылью / убытками. Стратегия определяет сроки входа через перекрестки индикаторов, использует теорию Мартингейла для управления позициями и повышает доходность посредством пирамиды на трендовых рынках.

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

Основная логика состоит из четырех ключевых элементов: сигналов входа, механизма добавления позиций, управления прибылью/убытками и контроля риска. Сигналы входа основаны на сближении линии MACD, пересекающей линию сигнала, и %K KDJs, пересекающей линию %D; механизм добавления позиций использует теорию Мартингейла, динамически регулируя размер позиции с помощью коэффициента множителя, поддерживая до 10 дополнительных позиций; прием прибыли использует остановки для динамической корректировки уровней получения прибыли; стоп-лосс включает как фиксированные, так и остановки механизмов. Стратегия поддерживает гибкую корректировку параметров индикатора, параметров контроля позиции и параметров контроля риска.

Преимущества стратегии

  1. Высокая надежность сигнальной системы: сочетает в себе индикатор тренда MACD и осциллятор KDJ для эффективной фильтрации ложных сигналов
  2. Научное управление позициями: система Мартингейла может снизить затраты на хранение путем добавления позиций в контртенденции
  3. Всеобъемлющий контроль рисков: многочисленные механизмы стоп-лосса и лимиты позиций эффективно контролируют риск
  4. Оптимизированная структура доходности: пирамида может достичь лучшей доходности на трендовых рынках
  5. Гибкие параметры: поддерживает оптимизацию параметров стратегии для различных рыночных характеристик

Стратегические риски

  1. Рыночный риск: частое увеличение позиций на различных рынках может привести к увеличению потерь
  2. Риск позиций: система Мартингейла может привести к чрезмерному размеру позиций
  3. Риск ликвидности: крупное вложение капитала может вызвать недостаточные проблемы с ликвидностью
  4. Системный риск: чрезмерная оптимизация параметров может привести к перенастройке стратегии

Направления оптимизации стратегии

  1. Оптимизация системы сигналов: включение показателей волатильности для корректировки чувствительности сигнала в условиях высокой волатильности
  2. Оптимизация управления позициями: Разработка динамических коэффициентов множителя для адаптивной корректировки на основе рыночных условий
  3. Оптимизация управления рисками: Добавление модуля управления привлечением для сокращения позиций во время значительных привлечений
  4. Оптимизация параметров: внедрение методов машинного обучения для адаптивной корректировки параметров

Резюме

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


/*backtest
start: 2024-11-04 00:00:00
end: 2024-12-04 00:00:00
period: 1h
basePeriod: 1h
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

// This Pine Script™ code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © aaronxu567
//@version=5
strategy("MACD and KDJ Opening Conditions with Pyramiding and Exit", overlay=true) // pyramiding

// Setting
initialOrder = input.float(50000.0, title="Initial Order") 
initialOrderSize = initialOrder/close
//initialOrderSize = input.float(1.0, title="Initial Order Size") // Initial Order Size
macdFastLength = input.int(9, title="MACD Fast Length") // MACD Setting
macdSlowLength = input.int(26, title="MACD Slow Length")
macdSignalSmoothing = input.int(9, title="MACD Signal Smoothing")
kdjLength = input.int(14, title="KDJ Length")
kdjSmoothK = input.int(3, title="KDJ Smooth K")
kdjSmoothD = input.int(3, title="KDJ Smooth D")
enableLong = input.bool(true, title="Enable Long Trades")
enableShort = input.bool(true, title="Enable Short Trades")

// Additions Setting
maxAdditions = input.int(5, title="Max Additions", minval=1, maxval=10) // Max Additions
addPositionPercent = input.float(1.0, title="Add Position Percent", minval=0.1, maxval=10) // Add Conditions
reboundPercent = input.float(0.5, title="Rebound Percent (%)", minval=0.1, maxval=10) // Rebound 
addMultiplier = input.float(1.0, title="Add Multiplier", minval=0.1, maxval=10) // 

// Stop Setting
takeProfitTrigger = input.float(2.0, title="Take Profit Trigger (%)", minval=0.1, maxval=10) // 
trailingStopPercent = input.float(0.3, title="Trailing Stop (%)", minval=0.1, maxval=10) // 
stopLossPercent = input.float(6.0, title="Stop Loss Percent", minval=0.1, maxval=10) // 

// MACD Calculation
[macdLine, signalLine, _] = ta.macd(close, macdFastLength, macdSlowLength, macdSignalSmoothing)

// KDJ Calculation
k = ta.sma(ta.stoch(close, high, low, kdjLength), kdjSmoothK)
d = ta.sma(k, kdjSmoothD)
j = 3 * k - 2 * d

// Long Conditions
enterLongCondition = enableLong and ta.crossover(macdLine, signalLine) and ta.crossover(k, d)

// Short Conditions
enterShortCondition = enableShort and ta.crossunder(macdLine, signalLine) and ta.crossunder(k, d)

// Records
var float entryPriceLong = na
var int additionsLong = 0 // 记录多仓加仓次数
var float nextAddPriceLong = na // 多仓下次加仓触发价格
var float lowestPriceLong = na // 多头的最低价格
var bool longPending = false // 多头加仓待定标记

var float entryPriceShort = na
var int additionsShort = 0 // 记录空仓加仓次数
var float nextAddPriceShort = na // 空仓下次加仓触发价格
var float highestPriceShort = na // 空头的最高价格
var bool shortPending = false // 空头加仓待定标记

var bool plotEntryLong = false
var bool plotAddLong = false
var bool plotEntryShort = false
var bool plotAddShort = false

// Open Long
if (enterLongCondition and strategy.opentrades == 0)
    strategy.entry("long", strategy.long, qty=initialOrderSize,comment = 'Long')
    entryPriceLong := close
    nextAddPriceLong := close * (1 - addPositionPercent / 100)
    additionsLong := 0
    lowestPriceLong := na
    longPending := false
    plotEntryLong := true

// Add Long
if (strategy.position_size > 0 and additionsLong < maxAdditions)
    // Conditions Checking
    if (close < nextAddPriceLong) and not longPending
        lowestPriceLong := close
        longPending := true

    if (longPending)
        // Rebound Checking
        if (close > lowestPriceLong * (1 + reboundPercent / 100))
            // Record Price
            float addQty = initialOrderSize*math.pow(addMultiplier,additionsLong+1)
            strategy.entry("long", strategy.long, qty=addQty,comment = 'Add Long')
            additionsLong += 1
            longPending := false
            nextAddPriceLong := math.min(nextAddPriceLong, close) * (1 - addPositionPercent / 100) // Price Updates
            plotAddLong := true
        else
            lowestPriceLong := math.min(lowestPriceLong, close)

// Open Short
if (enterShortCondition and strategy.opentrades == 0)
    strategy.entry("short", strategy.short, qty=initialOrderSize,comment = 'Short')
    entryPriceShort := close
    nextAddPriceShort := close * (1 + addPositionPercent / 100)
    additionsShort := 0
    highestPriceShort := na
    shortPending := false
    plotEntryShort := true

// add Short
if (strategy.position_size < 0 and additionsShort < maxAdditions)
    // Conditions Checking
    if (close > nextAddPriceShort) and not shortPending
        highestPriceShort := close
        shortPending := true

    if (shortPending)
        // rebound Checking
        if (close < highestPriceShort * (1 - reboundPercent / 100))
            // Record Price
            float addQty = initialOrderSize*math.pow(addMultiplier,additionsShort+1)
            strategy.entry("short", strategy.short, qty=addQty,comment = "Add Short")
            additionsShort += 1
            shortPending := false
            nextAddPriceShort := math.max(nextAddPriceShort, close) * (1 + addPositionPercent / 100) // Price Updates
            plotAddShort := true
        else
            highestPriceShort := math.max(highestPriceShort, close)

// Take Profit or Stop Loss
if (strategy.position_size != 0)
    float stopLossLevel = strategy.position_avg_price * (strategy.position_size > 0 ? (1 - stopLossPercent / 100) : (1 + stopLossPercent / 100))
    float trailOffset = strategy.position_avg_price * (trailingStopPercent / 100) / syminfo.mintick

    if (strategy.position_size > 0)
        strategy.exit("Take Profit/Stop Loss", from_entry="long", stop=stopLossLevel, trail_price=strategy.position_avg_price * (1 + takeProfitTrigger / 100), trail_offset=trailOffset)
    else
        strategy.exit("Take Profit/Stop Loss", from_entry="short", stop=stopLossLevel, trail_price=strategy.position_avg_price * (1 - takeProfitTrigger / 100), trail_offset=trailOffset)

// Plot
plotshape(series=plotEntryLong, location=location.belowbar, color=color.blue, style=shape.triangleup, size=size.small, title="Long Signal")
plotshape(series=plotAddLong, location=location.belowbar, color=color.green, style=shape.triangleup, size=size.small, title="Add Long Signal")
plotshape(series=plotEntryShort, location=location.abovebar, color=color.red, style=shape.triangledown, size=size.small, title="Short Signal")
plotshape(series=plotAddShort, location=location.abovebar, color=color.orange, style=shape.triangledown, size=size.small, title="Add Short Signal")

// Plot Clear
plotEntryLong := false
plotAddLong := false
plotEntryShort := false
plotAddShort := false



// // table
// var infoTable = table.new(position=position.top_right,columns = 2,rows = 6,bgcolor=color.yellow,frame_color = color.white,frame_width = 1,border_width = 1,border_color = color.black)
// if barstate.isfirst
//     t1="Open Price"
//     t2="Avg Price"
//     t3="Additions"
//     t4='Next Add Price'
//     t5="Take Profit"
//     t6="Stop Loss"
//     table.cell(infoTable, column = 0, row = 0,text=t1       ,text_size=size.auto)
//     table.cell(infoTable, column = 0, row = 1,text=t2       ,text_size=size.auto)
//     table.cell(infoTable, column = 0, row = 2,text=t3       ,text_size=size.auto)
//     table.cell(infoTable, column = 0, row = 3,text=t4       ,text_size=size.auto)
//     table.cell(infoTable, column = 0, row = 4,text=t5       ,text_size=size.auto)
//     table.cell(infoTable, column = 0, row = 5,text=t6       ,text_size=size.auto)
// if barstate.isconfirmed and strategy.position_size!=0
//     ps=strategy.position_size
//     pos_avg=strategy.position_avg_price
//     opt=strategy.opentrades
//     t1=str.tostring(strategy.opentrades.entry_price(0),format.mintick)
//     t2=str.tostring(pos_avg,format.mintick)
//     t3=str.tostring(opt>1?(opt-1):0)
//     t4=str.tostring(ps>0?nextAddPriceLong:nextAddPriceShort,format.mintick)
//     t5=str.tostring(pos_avg*(1+(ps>0?1:-1)*takeProfitTrigger*0.01),format.mintick)
//     t6=str.tostring(pos_avg*(1+(ps>0?-1:1)*stopLossPercent*0.01),format.mintick)
//     table.cell(infoTable, column = 1, row = 0,text=t1  ,text_size=size.auto)
//     table.cell(infoTable, column = 1, row = 1,text=t2  ,text_size=size.auto)
//     table.cell(infoTable, column = 1, row = 2,text=t3  ,text_size=size.auto)
//     table.cell(infoTable, column = 1, row = 3,text=t4  ,text_size=size.auto)
//     table.cell(infoTable, column = 1, row = 4,text=t5  ,text_size=size.auto)
//     table.cell(infoTable, column = 1, row = 5,text=t6  ,text_size=size.auto)
    

Связанные

Больше