Tài nguyên đang được tải lên... tải...

Chiến lược giao dịch định kim định lượng kết hợp MACD-KDJ Martingale

Tác giả:ChaoZhang, Ngày: 2024-12-05 16:35:26
Tags:MACDKDJSMA

 MACD-KDJ Combined Martingale Pyramiding Quantitative Trading Strategy

Tổng quan

Chiến lược này là một hệ thống giao dịch Martingale dựa trên các chỉ số MACD và KDJ, kết hợp kích cỡ vị trí kim tự tháp và quản lý lợi nhuận / lỗ năng động. Chiến lược xác định thời gian vào thông qua các dấu hiệu chéo, sử dụng lý thuyết Martingale để quản lý vị trí và tăng lợi nhuận thông qua kim tự tháp trong các thị trường xu hướng. Nó có một hệ thống kiểm soát rủi ro toàn diện bao gồm kiểm soát vị trí tổng thể, cơ chế dừng lỗ năng động và cơ chế kiểm soát rút tiền.

Nguyên tắc chiến lược

Cơ sở logic bao gồm bốn yếu tố chính: tín hiệu nhập cảnh, cơ chế thêm vị trí, quản lý lợi nhuận / lỗ và kiểm soát rủi ro. Các tín hiệu nhập cảnh dựa trên sự hội tụ của đường MACD vượt qua đường tín hiệu và đường KDJ% K vượt qua đường % D; cơ chế thêm vị trí áp dụng lý thuyết Martingale, điều chỉnh kích thước vị trí một cách năng động thông qua một yếu tố nhân, hỗ trợ tối đa 10 vị trí bổ sung; Lợi nhuận sử dụng dừng lại để điều chỉnh mức lợi nhuận một cách năng động; dừng lỗ bao gồm cả cơ chế cố định và chậm. Chiến lược hỗ trợ điều chỉnh linh hoạt các tham số chỉ số, tham số kiểm soát vị trí và tham số kiểm soát rủi ro.

Ưu điểm chiến lược

  1. Độ tin cậy hệ thống tín hiệu cao: Kết hợp chỉ số xu hướng MACD và dao động KDJ để lọc hiệu quả các tín hiệu sai
  2. Quản lý vị trí khoa học: Hệ thống Martingale có thể giảm chi phí nắm giữ bằng cách thêm các vị trí trong các xu hướng ngược
  3. Kiểm soát rủi ro toàn diện: Nhiều cơ chế dừng lỗ và giới hạn vị trí kiểm soát rủi ro hiệu quả
  4. Cấu trúc lợi nhuận tối ưu hóa: Pyramiding có thể đạt được lợi nhuận tốt hơn trong các thị trường xu hướng
  5. Các thông số linh hoạt: Hỗ trợ tối ưu hóa các thông số chiến lược cho các đặc điểm thị trường khác nhau

Rủi ro chiến lược

  1. Rủi ro thị trường: Sự gia tăng thường xuyên các vị trí trên các thị trường khác nhau có thể dẫn đến tổn thất lớn hơn
  2. Rủi ro vị thế: Hệ thống Martingale có thể dẫn đến kích thước vị thế quá lớn
  3. Rủi ro thanh khoản: Việc triển khai vốn lớn có thể phải đối mặt với các vấn đề thanh khoản không đủ
  4. Rủi ro hệ thống: Tối ưu hóa tham số quá mức có thể dẫn đến quá mức điều chỉnh chiến lược

Hướng dẫn tối ưu hóa chiến lược

  1. Tối ưu hóa hệ thống tín hiệu: Kết hợp các chỉ số biến động để điều chỉnh độ nhạy tín hiệu trong môi trường biến động cao
  2. Tối ưu hóa quản lý vị trí: Thiết kế các yếu tố nhân động để điều chỉnh thích nghi dựa trên điều kiện thị trường
  3. Tối ưu hóa kiểm soát rủi ro: Thêm mô-đun kiểm soát rút vốn để giảm các vị trí trong thời gian rút vốn đáng kể
  4. Tối ưu hóa tham số: giới thiệu các phương pháp học máy để điều chỉnh tham số thích nghi

Tóm lại

Chiến lược này xây dựng một hệ thống giao dịch định lượng hoàn chỉnh bằng cách kết hợp các chỉ số kỹ thuật cổ điển với các phương pháp quản lý vị trí tiên tiến. Những lợi thế cốt lõi của nó nằm ở độ tin cậy tín hiệu và kiểm soát rủi ro toàn diện, trong khi duy trì khả năng thích nghi mạnh mẽ thông qua các thông số. Mặc dù có rủi ro vốn có, tối ưu hóa và cải tiến liên tục cho phép chiến lược duy trì hiệu suất ổn định trong các môi trường thị trường khác nhau.


/*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)
    

Có liên quan

Thêm nữa