資源の読み込みに... 荷物...

MACD-KDJ 組み合わせたマルティンゲール・ピラミディング量的な取引戦略

作者: リン・ハーンチャオチャン, 日付: 2024-12-05 16:35:26
タグ:マックドKDJSMA

 MACD-KDJ Combined Martingale Pyramiding Quantitative Trading Strategy

概要

この戦略はMACDおよびKDJ指標に基づいたマルティンゲール取引システムで,ピラミッド型ポジションサイズとダイナミックな利益/損失管理を組み合わせています.この戦略は,指標クロスオーバーを通じてエントリータイミングを決定し,ポジション管理のためにマルティンゲール理論を使用し,トレンド市場でのピラミッド型取引を通じてリターンを向上させます.総ポジション制御,ダイナミックストップ・ロース,引き下げ制御メカニズムを含む包括的なリスク管理システムがあります.

戦略の原則

基本論理は,エントリー信号,ポジション追加メカニズム,利益/損失管理,リスク制御の4つの主要要素で構成される.エントリー信号は,信号ラインを横断するMACDラインと%Dラインを横断するKDJ%Kの収束に基づいている.ポジション追加メカニズムはマルティンゲール理論を採用し,倍数因子によってポジションサイズを動的に調整し,最大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)
    

関連性

もっと