Chiến lược giao cắt đường trung bình động nhiều kỳ


Ngày tạo: 2023-10-09 16:41:04 sửa đổi lần cuối: 2023-10-09 16:41:04
sao chép: 2 Số nhấp chuột: 651
1
tập trung vào
1617
Người theo dõi

Tổng quan

Chiến lược này dựa trên hệ thống chéo của các đường trung bình di chuyển, thông qua các chu kỳ khác nhau của đường trung bình di chuyển golden cross và cross death để đánh giá thời gian mua và bán. Chiến lược này kết hợp với các chức năng theo dõi xu hướng như dừng lỗ, dừng lỗ, dừng lỗ để khóa lợi nhuận và tránh rủi ro.

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

Chiến lược này sử dụng hai nhóm trung bình di chuyển, tức là đường nhanh và đường chậm. Chu kỳ đường nhanh ngắn, đại diện cho xu hướng ngắn hạn; chu kỳ đường dài, đại diện cho xu hướng dài hạn. Khi đường nhanh từ phía dưới phá vỡ đường chậm, tạo ra một đường giao thoa vàng, cho thấy thị trường chuyển đổi từ bò sang bò, làm nhiều; khi đường nhanh từ phía trên xuống phá vỡ đường chậm, tạo ra một đường giao thoa chết, cho thấy thị trường chuyển đổi từ bò sang gấu, làm không.

Trong mã, chỉ số đường nhanh là ma1 và đường chậm là ma2. Cả ma1 và ma2 đều có thể chọn các loại trung bình di chuyển khác nhau, chẳng hạn như SMA, EMA, v.v., và có thể đặt các tham số chu kỳ khác nhau. ma1 đại diện cho xu hướng ngắn hạn, chu kỳ ngắn hơn; ma2 đại diện cho xu hướng dài hạn, chu kỳ dài hơn.

Khi ma1 vàng ma2 , tạo ra tín hiệu dài, làm nhiều; khi ma1 chết ma2 , tạo ra tín hiệu ngắn, làm trắng. Khi giao dịch thực tế, có thể kết hợp các chức năng theo dõi xu hướng như dừng lỗ, dừng lỗ, dừng lỗ để khóa lợi nhuận và tránh rủi ro.

Phân tích lợi thế

Chiến lược này có những ưu điểm sau:

  1. Chiến lược của chúng tôi rất đơn giản, rõ ràng, dễ hiểu và dễ thực hiện.

  2. Có khả năng lựa chọn trung bình di chuyển linh hoạt cho các loại và tham số khác nhau, phù hợp với các môi trường thị trường khác nhau.

  3. Thiết kế đa chu kỳ, nắm bắt cả xu hướng ngắn hạn và dài hạn, tránh bị bỏ lỡ.

  4. Điều kiện mở vị trí tùy chỉnh, kiểm soát chặt chẽ tần suất giao dịch.

  5. Có thể thiết lập các điều kiện dừng, dừng và kiểm soát rủi ro hiệu quả.

  6. Bạn có thể thêm theo dõi xu hướng để theo dõi lợi nhuận.

  7. Các tham số có thể được tối ưu hóa để làm cho chiến lược ổn định và đáng tin cậy hơn.

Phân tích rủi ro

Chiến lược này cũng có những rủi ro sau:

  1. Các giao điểm giữa hai đường trung bình di chuyển bị chậm trễ, có thể bỏ lỡ thời điểm tốt nhất để giá đảo ngược.

  2. Thời gian chuyển động trung bình không được thiết lập đúng, có thể tạo ra nhiều tín hiệu giả hơn.

  3. Sự kiện đột ngột gây ra sự đảo ngược nhanh chóng, ngăn chặn nguy cơ bị bắn hạ.

  4. Trong một xu hướng, có nhiều khả năng giá sẽ ở bên đường trung bình trong một thời gian dài.

  5. Các tham số được tối ưu hóa không đúng, có thể được tối ưu hóa quá mức trong một khoảng thời gian nhất định.

Các biện pháp quản lý rủi ro:

  1. Kết hợp với các chỉ số khác để lọc tín hiệu, tránh phá vỡ giả.

  2. Cài đặt chu kỳ theo nguyên tắc giao dịch xu hướng, kiểm tra các tham số tối ưu hóa.

  3. Kiểm soát rủi ro một cách thận trọng và thiết lập vị trí dừng lỗ một cách hợp lý.

  4. Một số chi phí cho việc chờ đợi kiên nhẫn.

  5. Kiểm tra sức mạnh của các tham số trong nhiều môi trường thị trường.

Hướng tối ưu hóa

Chiến lược này có thể được tối ưu hóa bằng cách:

  1. Kiểm tra nhiều loại trung bình di chuyển hơn, chẳng hạn như trung bình di chuyển có trọng lượng.

  2. Thêm chu kỳ động dựa trên biến động, điều chỉnh tham số đường trung bình theo thay đổi của thị trường.

  3. Điều kiện nhập cảnh chiến lược có thể được thêm vào thời gian hoặc lọc cơ bản, giảm tỷ lệ giao dịch sai.

  4. Các điều kiện xuất cảnh có thể được thiết lập động dừng dừng lỗ, điều chỉnh mức dừng lỗ theo mức độ biến động của thị trường.

  5. Có thể xây dựng hệ thống tối ưu hóa tham số để thực hiện phản hồi lịch sử và điều chỉnh tham số của chiến lược.

  6. Thêm thuật toán học máy, sử dụng AI để tối ưu hóa tham số và lọc tín hiệu.

Tóm tắt

Chiến lược này có thể đạt được lợi nhuận ổn định bằng cách chọn các tham số phù hợp, tối ưu hóa logic đầu ra và kiểm soát rủi ro nghiêm ngặt. Tuy nhiên, người dùng cần phải chịu một số chi phí sau khi nhận ra rủi ro và thời gian chờ. Nhìn chung, chiến lược này đơn giản và thực tế, đáng để tối ưu hóa tham số và kiểm soát rủi ro để thích ứng với nhiều môi trường thị trường hơn.

Mã nguồn chiến lược
/*backtest
start: 2023-09-08 00:00:00
end: 2023-10-08 00:00:00
period: 4h
basePeriod: 15m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

//@version=3
// The majority of this script I took from the Autoview website. There are some typos in the original that I've fixed, some things I've added, things I will add, and I'm tired pulling my strategy code out and uploading this to pastebin for people.
// DISCLAIMER: I am not a financial advisor, this is not financial advice, do not use this code without first doing your own research, etc, etc, it's not my fault when you lose your house.

strategy("Moving Averages Cross - MTF - Strategy", "MA Cross", overlay=true, pyramiding=0, initial_capital=100000, currency=currency.USD, default_qty_type = strategy.percent_of_equity, default_qty_value = 100, commission_type=strategy.commission.percent, commission_value=0.1)

bgcolor ( color=black, transp=40, title='Blackground', editable=true)

///////////////////////////////////////////////
//* Backtesting Period Selector | Component *//
///////////////////////////////////////////////

//* https://www.tradingview.com/script/eCC1cvxQ-Backtesting-Period-Selector-Component *//
//* https://www.tradingview.com/u/pbergden/ *//
//* Modifications made *//

testStartYear = input(2018, "Backtest Start Year") 
testStartMonth = input(1, "Backtest Start Month")
testStartDay = input(1, "Backtest Start Day")
testPeriodStart = timestamp(testStartYear,testStartMonth,testStartDay,00,00)

testStopYear = input(9999, "Backtest Stop Year")
testStopMonth = input(12, "Backtest Stop Month")
testStopDay = input(31, "Backtest Stop Day")
testPeriodStop = timestamp(testStopYear,testStopMonth,testStopDay,0,0)

testPeriod() => true

/////////////////////////////////////
//* Put your strategy logic below *//
/////////////////////////////////////

sp1 = input("----", title="--------Moving Average 1----------", options=["----"])
maUseRes1   = input(defval = false, title = "Use Different Resolution?")
//maReso1     = input(defval = "60", title = "Set Resolution", type = resolution)
maReso1     = input(defval='60', title = "Set Resolution Minutes")
maType1     = input("EMA", title="MA", options=["SMA", "EMA", "DEMA", "TEMA", "WMA", "VWMA", "SMMA", "Hull", "LSMA", "ALMA"])
maSource1   = input(defval = close, title = "Source")
maLength1   = input(defval = 15, title = "Period", minval = 1)
lsmaOffset1 = input(defval = 1, title = "Least Squares (LSMA) Only - Offset Value", minval = 0)
almaOffset1 = input(defval = 0.85, title = "Arnaud Legoux (ALMA) Only - Offset Value", minval = 0, step = 0.01)
almaSigma1  = input(defval = 6, title = "Arnaud Legoux (ALMA) Only - Sigma Value", minval = 0)

sp2 = input("----", title="--------Moving Average 2----------", options=["----"])
maUseRes2   = input(defval = false, title = "Use Different Resolution?")
//maReso2    = input(defval = "60", title = "Set Resolution", type = resolution)
maReso2     = input(defval='60', title = "Set Resolution Minutes")
maType2    = input("EMA", title="MA", options=["SMA", "EMA", "DEMA", "TEMA", "WMA", "VWMA", "SMMA", "Hull", "LSMA", "ALMA"])
maSource2   = input(defval = close, title = "Source")
maLength2   = input(defval = 30, title = "Period", minval = 1)
lsmaOffset2 = input(defval = 1, title = "Least Squares (LSMA) Only - Offset Value", minval = 0)
almaOffset2 = input(defval = 0.85, title = "Arnaud Legoux (ALMA) Only - Offset Value", minval = 0, step = 0.01)
almaSigma2  = input(defval = 6, title = "Arnaud Legoux (ALMA) Only - Sigma Value", minval = 0)

//Function from @JayRogers thank you man awesome work
variant(type, src, len, lsmaOffset, almaOffset, almaSigma) =>
    v1 = sma(src, len)                                                  // Simple
    v2 = ema(src, len)                                                  // Exponential
    v3 = 2 * v2 - ema(v2, len)                                          // Double Exponential
    v4 = 3 * (v2 - ema(v2, len)) + ema(ema(v2, len), len)               // Triple Exponential
    v5 = wma(src, len)                                                  // Weighted
    v6 = vwma(src, len)                                                 // Volume Weighted
    v7 = na(v5[1]) ? sma(src, len) : (v5[1] * (len - 1) + src) / len    // Smoothed
    v8 = wma(2 * wma(src, len / 2) - wma(src, len), round(sqrt(len)))   // Hull
    v9 = linreg(src, len, lsmaOffset)                                   // Least Squares
    v10 = alma(src, len, almaOffset, almaSigma)                         // Arnaud Legoux
    type=="EMA"?v2 : type=="DEMA"?v3 : type=="TEMA"?v4 : type=="WMA"?v5 : type=="VWMA"?v6 : type=="SMMA"?v7 : type=="Hull"?v8 : type=="LSMA"?v9 : type=="ALMA"?v10 : v1
//Different resolution function    
reso(exp, res, use) => use ? security(tickerid, res, exp) : exp    
    
ma1 = reso(variant(maType1, maSource1, maLength1, lsmaOffset1, almaOffset1, almaSigma1), maReso1, maUseRes1)
ma2 = reso(variant(maType2, maSource2, maLength2, lsmaOffset2, almaOffset2, almaSigma2), maReso2, maUseRes2)

plotma1 = plot(ma1, color=green, tranps=50, linewidth = 2 )
plotma2 = plot(ma2, color=red,   tranps=50, linewidth = 2 )

// Long/Short Logic
longLogic =  crossover(ma1,ma2) ? 1 : 0
shortLogic = crossunder(ma1,ma2) ? 1 : 0

//////////////////////////
//* Strategy Component *//
//////////////////////////

isLong = input(false, "Longs Only")
isShort = input(false, "Shorts Only")
isFlip = input(false, "Flip the Opens")

long = longLogic
short = shortLogic

if isFlip
    long := shortLogic
    short := longLogic
else
    long := longLogic
    short := shortLogic

if isLong
    long := long
    short := na

if isShort
    long := na
    short := short
    
////////////////////////////////
//======[ Signal Count ]======//
////////////////////////////////

sectionLongs = 0
sectionLongs := nz(sectionLongs[1])
sectionShorts = 0
sectionShorts := nz(sectionShorts[1])

if long
    sectionLongs := sectionLongs + 1
    sectionShorts := 0

if short
    sectionLongs := 0
    sectionShorts := sectionShorts + 1

//////////////////////////////
//======[ Pyramiding ]======//
//////////////////////////////

pyrl = input(1, "Pyramiding less than") // If your count is less than this number
pyre = input(0, "Pyramiding equal to") // If your count is equal to this number
pyrg = input(1000000, "Pyramiding greater than") // If your count is greater than this number

longCondition = long and sectionLongs <= pyrl or long and sectionLongs >= pyrg or long and sectionLongs == pyre ? 1 : 0
shortCondition = short and sectionShorts <= pyrl or short and sectionShorts >= pyrg or short and sectionShorts == pyre ? 1 : 0

////////////////////////////////
//======[ Entry Prices ]======//
////////////////////////////////

last_open_longCondition = na
last_open_shortCondition = na
last_open_longCondition := longCondition ? close : nz(last_open_longCondition[1])
last_open_shortCondition := shortCondition ? close : nz(last_open_shortCondition[1])

////////////////////////////////////
//======[ Open Order Count ]======//
////////////////////////////////////

sectionLongConditions = 0
sectionLongConditions := nz(sectionLongConditions[1])
sectionShortConditions = 0
sectionShortConditions := nz(sectionShortConditions[1])

if longCondition
    sectionLongConditions := sectionLongConditions + 1
    sectionShortConditions := 0

if shortCondition
    sectionLongConditions := 0
    sectionShortConditions := sectionShortConditions + 1
    
///////////////////////////////////////////////
//======[ Position Check (long/short) ]======//
///////////////////////////////////////////////

last_longCondition = na
last_shortCondition = na
last_longCondition := longCondition ? time : nz(last_longCondition[1])
last_shortCondition := shortCondition ? time : nz(last_shortCondition[1])

in_longCondition = last_longCondition > last_shortCondition
in_shortCondition = last_shortCondition > last_longCondition

/////////////////////////////////////
//======[ Position Averages ]======//
/////////////////////////////////////

totalLongs = 0.0
totalLongs := nz(totalLongs[1])
totalShorts = 0.0
totalShorts := nz(totalShorts[1])
averageLongs = 0.0
averageLongs := nz(averageLongs[1])
averageShorts = 0.0
averageShorts := nz(averageShorts[1]) 

if longCondition
    totalLongs := totalLongs + last_open_longCondition
    totalShorts := 0.0

if shortCondition
    totalLongs := 0.0
    totalShorts := totalShorts + last_open_shortCondition

averageLongs := totalLongs / sectionLongConditions
averageShorts := totalShorts / sectionShortConditions

/////////////////////////////////
//======[ Trailing Stop ]======//
/////////////////////////////////

isTS = input(false, "Trailing Stop")
tsi = input(1000, "Activate Trailing Stop Price (%). Divided by 100 (1 = 0.01%)") / 100 
ts = input(575, "Trailing Stop (%). Divided by 100 (1 = 0.01%)") / 100

last_high = na
last_low = na
last_high_short = na
last_low_short = na
last_high := not in_longCondition ? na : in_longCondition and (na(last_high[1]) or high > nz(last_high[1])) ? high : nz(last_high[1])
last_high_short := not in_shortCondition ? na : in_shortCondition and (na(last_high[1]) or high > nz(last_high[1])) ? high : nz(last_high[1])
last_low := not in_shortCondition ? na : in_shortCondition and (na(last_low[1]) or low < nz(last_low[1])) ? low : nz(last_low[1])
last_low_short := not in_longCondition ? na : in_longCondition and (na(last_low[1]) or low < nz(last_low[1])) ? low : nz(last_low[1])

long_ts = isTS and not na(last_high) and low <= last_high - last_high / 100 * ts and longCondition == 0 and last_high >= averageLongs + averageLongs / 100 * tsi
short_ts = isTS and not na(last_low) and high >= last_low + last_low / 100 * ts and shortCondition == 0 and last_low <= averageShorts - averageShorts/ 100 * tsi

///////////////////////////////
//======[ Take Profit ]======//
///////////////////////////////

isTP = input(false, "Take Profit")
tp = input(300, "Take Profit (%). Divided by 100 (1 = 0.01%)") / 100
long_tp = isTP and close > averageLongs + averageLongs / 100 * tp and not longCondition
short_tp = isTP and close < averageShorts - averageShorts / 100 * tp and not shortCondition

/////////////////////////////
//======[ Stop Loss ]======//
/////////////////////////////

isSL = input(false, "Stop Loss")
sl = input(575, "Stop Loss (%). Divided by 100 (1 = 0.01%)") / 100
long_sl = isSL and close < averageLongs - averageLongs / 100 * sl and longCondition == 0
short_sl = isSL and close > averageShorts + averageShorts / 100 * sl and shortCondition == 0

/////////////////////////////////
//======[ Close Signals ]======//
/////////////////////////////////

longClose = long_tp or long_sl or long_ts  ? 1 : 0
shortClose = short_tp or short_sl or short_ts ? 1: 0

///////////////////////////////
//======[ Plot Colors ]======//
///////////////////////////////

longCloseCol = na
shortCloseCol = na
longCloseCol := long_tp ? purple : long_sl ? maroon : long_ts ? blue : longCloseCol[1]
shortCloseCol := short_tp ? purple : short_sl ? maroon : short_ts ? blue : shortCloseCol[1]
tpColor = isTP and in_longCondition ? purple : isTP and in_shortCondition ? purple : white
slColor = isSL and in_longCondition ? red : isSL and in_shortCondition ? red : white

//////////////////////////////////
//======[ Strategy Plots ]======//
//////////////////////////////////

// Comment out these lines to use alerts
plot(isTS and in_longCondition ? averageLongs + averageLongs / 100 * tsi : na, "Long Trailing Activate", blue, style=3, linewidth=2)
plot(isTS and in_longCondition and last_high >= averageLongs +  averageLongs / 100 * tsi ? last_high - last_high / 100 * ts : na, "Long Trailing", fuchsia, style=2, linewidth=3)
plot(isTS and in_shortCondition ? averageShorts - averageShorts/ 100 * tsi : na, "Short Trailing Activate", blue, style=3, linewidth=2)
plot(isTS and in_shortCondition and last_low <= averageShorts - averageShorts/ 100 * tsi ? last_low + last_low / 100 * ts : na, "Short Trailing", fuchsia, style=2, linewidth=3)
plot(isTP and in_longCondition and last_high < averageLongs + averageLongs / 100 * tp ? averageLongs + averageLongs / 100 * tp : na, "Long TP", tpColor, style=3, linewidth=2)
plot(isTP and in_shortCondition and last_low > averageShorts - averageShorts / 100 * tp ? averageShorts - averageShorts / 100 * tp : na, "Short TP", tpColor, style=3, linewidth=2)
plot(isSL and in_longCondition and last_low_short > averageLongs - averageLongs / 100 * sl ? averageLongs - averageLongs / 100 * sl : na, "Long SL", slColor, style=3, linewidth=2)
plot(isSL and in_shortCondition and last_high_short < averageShorts + averageShorts / 100 * sl ? averageShorts + averageShorts / 100 * sl : na, "Short SL", slColor, style=3, linewidth=2)

///////////////////////////////
//======[ Alert Plots ]======//
///////////////////////////////


// Uncomment to use Alerts, or the new Signal Plots, but not both
// Old Signal Plots
//plot(longCondition, "Long", green)
//plot(shortCondition, "Short", red)
//plot(longClose, "Long Close", longCloseCol)
//plot(shortClose, "Short Close", shortCloseCol)

// Uncomment for your alerts
//alertcondition(condition=longCondition, title="Long", message="")
//alertcondition(condition=shortCondition, title="Short", message="")
//alertcondition(condition=longClose, title="Long Close", message="")
//alertcondition(condition=shortClose, title="Short Close", message="")

///////////////////////////////////
//======[ Reset Variables ]======//
///////////////////////////////////

if longClose or not in_longCondition
    averageLongs := 0
    totalLongs := 0.0
    sectionLongs := 0
    sectionLongConditions := 0

if shortClose or not in_shortCondition
    averageShorts := 0
    totalShorts := 0.0
    sectionShorts := 0
    sectionShortConditions := 0

////////////////////////////////////////////
//======[ Strategy Entry and Exits ]======//
////////////////////////////////////////////

// Comment out to use alerts
if testPeriod()
    strategy.entry("Long", 1, when=longCondition)
    strategy.entry("Short", 0,  when=shortCondition)
    strategy.close("Long", when=longClose)
    strategy.close("Short", when=shortClose)