Xu hướng trung bình động đa yếu tố theo chiến lược

Tác giả:ChaoZhang, Ngày: 2024-01-18 12:07:52
Tags:

img

Tổng quan

Đây là một xu hướng trung bình di chuyển đơn giản sau chiến lược phù hợp với Bitcoin và Ethereum. Nó kết hợp nhiều chỉ số như trung bình di chuyển, MACD và RSI để xác định hướng xu hướng, và áp dụng kích thước vị trí cố định để theo dõi xu hướng dài hạn.

Chiến lược logic

Lý thuyết cốt lõi của chiến lược là đi dài khi EMA 20 ngày vượt qua trên SMA 100 ngày và SMA 100 ngày vượt qua trên SMA 200 ngày; đóng các vị trí khi EMA 20 ngày vượt qua dưới SMA 100 ngày.

Cụ thể, chiến lược tính toán các giá trị của đường EMA 20 ngày, đường SMA 100 ngày và đường SMA 200 ngày, và so sánh mối quan hệ kích thước của chúng để đánh giá xu hướng. Khi đường EMA 20 ngày vượt trên đường SMA 100 ngày, điều đó có nghĩa là giá đã bắt đầu tăng. Tại thời điểm này, nếu đường SMA 100 ngày cũng lớn hơn đường SMA 200 ngày, nó cho thấy xu hướng trung và dài hạn cũng đang tăng. Đây là một tín hiệu dài mạnh.

Sau khi nhập vào một vị trí dài, chiến lược sẽ tiếp tục giữ vị trí để theo xu hướng. Khi EMA 20 ngày vượt qua dưới SMA 100 ngày một lần nữa, nó cho thấy rằng một tín hiệu đảo ngược xu hướng ngắn hạn đã xảy ra. Tại thời điểm này, chiến lược sẽ chọn đóng các vị trí để dừng lỗ.

Ngoài ra, chiến lược cũng kết hợp các chỉ số như MACD và RSI để xác nhận xu hướng. Chỉ khi đường DIF, đường DEMA và đường thanh HIST của MACD đều tăng và chỉ số RSI trên 50, nó sẽ chọn mở các vị trí mua.

Ưu điểm

Ưu điểm lớn nhất của chiến lược này là nó xây dựng các quy tắc giao dịch xu hướng rõ ràng có thể theo dõi hiệu quả các xu hướng trung bình và dài hạn.

  1. Sử dụng nhiều đường trung bình động kết hợp để đánh giá xu hướng, tương đối đáng tin cậy.

  2. Sử dụng các vị trí nắm giữ dài hạn để theo dõi các biến động xu hướng mà không bị xáo trộn bởi biến động thị trường ngắn hạn.

  3. Kết hợp các chỉ số như MACD và RSI để xác nhận tín hiệu chiến lược có thể lọc các đột phá sai.

  4. Sử dụng chữ thập vàng và chữ thập chết của đường EMA và SMA để xác định các điểm nhập và xuất, các quy tắc đơn giản và rõ ràng.

  5. Có thể kiểm soát hiệu quả rủi ro bằng cách hạn chế lỗ thông qua dừng lỗ.

Rủi ro và giải pháp

Có một số rủi ro với chiến lược này. Vấn đề chính là nó không thể ngăn chặn tổn thất kịp thời khi xu hướng đảo ngược. Những rủi ro và giải pháp cụ thể là như sau:

  1. Không thể theo dõi các điểm đảo ngược xu hướng trong thời gian: Giảm chu kỳ trung bình động hoặc thêm nhiều chỉ số để đánh giá toàn diện.

  2. Thời gian giữ lâu có thể dễ dàng dẫn đến tổn thất lớn hơn: Gióng ngắn các đường ra đúng cách để dừng lỗ kịp thời.

  3. Các chỉ số trung bình động có xu hướng chậm lại: Thêm một tỷ lệ phần trăm nhất định của các đường dừng lỗ cho lỗ dừng hoạt động.

Hướng dẫn tối ưu hóa

Chiến lược này cũng có thể được tối ưu hóa trong các khía cạnh sau:

  1. Kiểm tra nhiều kết hợp các chu kỳ trung bình động để tìm các thông số tối ưu.

  2. Hãy thử các chỉ số hoặc mô hình khác để đánh giá xu hướng và thời gian nhập cảnh.

  3. Sử dụng máy học và các phương pháp khác để tối ưu hóa các thông số một cách năng động. Ví dụ, sử dụng học tăng cường để điều chỉnh kích thước dừng mất mát.

  4. Tích hợp các chỉ số khối lượng giao dịch để tránh sự phá vỡ sai. Ví dụ, về khối lượng số dư, khối lượng giao dịch, vv.

  5. Phát triển các hệ thống dừng lỗ tự động và theo dõi dừng lỗ có thể điều chỉnh các vị trí dừng lỗ dựa trên điều kiện thị trường.

Kết luận

Tóm lại, chiến lược này là một chiến lược theo xu hướng đơn giản và thẳng thắn. Nó sử dụng đường trung bình động để xác định hướng xu hướng, MACD và RSI để lọc tín hiệu. Sử dụng thời gian giữ tương đối dài để theo dõi chuyển động xu hướng. Nó có thể nắm bắt hiệu quả các cơ hội xu hướng trung và dài hạn.


/*backtest
start: 2024-01-16 00:00:00
end: 2024-01-17 00:00:00
period: 10m
basePeriod: 1m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

//@version=4
strategy(title="BTC_Long_Only_TV01_200507", overlay=true)

//////////// !!!!!!!!!!!!!!!! WORK BEST IN 2 HOURS for BTC, ETH and ETHXBT !!!!!!!!!!!!!!!!!!! /////////////////////
//280820 - After long esting this is the best script for ETHUSD in 4 hours. From 01/01/2020 til 28/08/2020


[macdLine, macdSignalLine, macdHist] = macd(close, 12, 26, 7)  

//_rsi_len = input(14, title="RSI length")
_rsi_len = 14 
  
NewValue = 0
PreviousValue = 0
leverage = 1

smaPercentageIncrease = 0.0
SMA_PERCENT_INCREASE = 0.0
float atrValue = 0
bool bPositionOpened = false
float stockPositionSize = 0 
float volatilityPercentage = 0.0
bool bDisplayArrow = false 
bool bEMAIsRising = false
bool bSMAIsRising = false
bool bSMASlowIsRising = false
bool bMACDIsRising = false
bool bMACDHistIsRising = false
bool bMACDSignalIsRising = false

float stopLoss = input (5, "StopLoss in %", type=input.float) //StopLoss associated with the order
//Best for alt versus BTC float stopLoss = input (3, "StopLoss in %", type=input.float) //StopLoss associated with the order 
float positionSize = 1000
float currentPrice = close 
float stopLossPrice = 0
float entryPrice = 0


//-----------------------------------------------------------


// === INPUT BACKTEST RANGE ONE YEAR 
//FromDay   = input(defval = 01, title = "From Day", minval = 1, maxval = 31)
//FromMonth = input(defval = 01, title = "From Month", minval = 1, maxval = 12)
//FromYear  = input(defval = 2020, title = "From Year", minval = 2017)
FromDay   = 01
FromMonth = 01
FromYear  = 2020

//ToDay     = input(defval = 01, title = "To Day", minval = 1, maxval = 31)
//ToMonth   = input(defval = 01, title = "To Month", minval = 1, maxval = 12)
//ToYear    = input(defval = 2023, title = "To Year", minval = 2017)
ToDay     = 14
ToMonth   = 05
ToYear    = 2029

// === FUNCTION EXAMPLE ===
start     = timestamp(FromYear, FromMonth, FromDay, 00, 00)  // backtest start window
finish    = timestamp(ToYear, ToMonth, ToDay, 23, 59)        // backtest finish window
window()  => true // create function "within window of time"


//FUNCTION DEFINITIONS
//----------------------
IsRising(data, loopBack) =>
    bIsRising = true
    for n = 1 to loopBack
        if data[n] > data[n-1]
            bIsRising := false
        continue
    bIsRising
    
IsFalling(data, loopBack) =>
    bIsFalling = true
    for n = 1 to loopBack
        if data[n] < data[n-1]
            bIsFalling := false
        continue
    bIsFalling
    
// END OF FUNCTION DEFINITIONS //


emaLength = 20
smaLength = 100
smaSlowLength = 200
 
ema = ema(close, emaLength) 
sma = sma(close, smaLength)
smaSlow = sma(close, smaSlowLength)

plot(sma, color=color.green)
plot(smaSlow, color=color.orange)
plot(ema, color=color.yellow)

//reload previous values
stopLossPrice := na(stopLossPrice[1]) ? 0.0 : stopLossPrice[1]
entryPrice := na(entryPrice[1]) ? 0.0 : entryPrice[1]
bPositionOpened := na(bPositionOpened[1]) ? false : bPositionOpened[1]
positionSize := na(positionSize[1]) ? 1000 : positionSize[1]
stockPositionSize := na(stockPositionSize[1]) ? 0 : stockPositionSize[1]
//leverage := na(leverage[1]) ? 1 : leverage[1]

bEMAIsRising := IsRising(ema, 2) 
bSMAIsRising := IsRising(sma, 3)
bMACDIsRising := IsRising(macdLine, 3)
bMACDHistIsRising := IsRising(macdHist, 1)
bSMASlowIsRising := IsRising(smaSlow, 10)
bMACDSignalIsRising := IsRising(macdSignalLine, 3)


atrValue := atr(14)
volatilityPercentage := (atrValue/currentPrice)*100 //calcute the volatility. Percentage of the actual price

 
if (window()) 
    //Check if we can open a LONG
    if (bPositionOpened == false and bSMASlowIsRising == true and bMACDIsRising == true and bEMAIsRising == true and bSMAIsRising == true and ema[0] > sma[0] and sma[0] < currentPrice)
        //Enter in short position 
        stockPositionSize := (positionSize*leverage)/currentPrice //Calculate the position size based on the actual price and the position Size (in $) configured.
        
        //calculate exit values
        stopLossPrice := currentPrice*(1-stopLoss/100) 
        strategy.entry("myPosition", strategy.long, qty=stockPositionSize, comment="BUY at " + tostring(currentPrice))
        entryPrice := currentPrice //store the entry price
        bPositionOpened := true  
        bDisplayArrow := true 
        
    if (bPositionOpened == true and (currentPrice <= stopLossPrice or crossunder(ema[1], sma[1])))
        strategy.close("myPosition", comment="" + tostring(currentPrice) ) //Stop
        //uncomment the below line to make the bot investing the full portfolio amount to test compounding effect.
        //positionSize := positionSize + ((stockPositionSize * currentPrice) - (positionSize*leverage)) 
        //reset some flags 
        bPositionOpened := false 
        bDisplayArrow := true 
        entryPrice := 0.0
        


Thêm nữa