Chiến lược giao dịch dao động cầu vồng

Tác giả:ChaoZhang, Ngày: 2024-02-23 14:57:43
Tags:

img

Tổng quan

Chiến lược giao dịch của Rainbow Oscillator chủ yếu sử dụng nhiều đường trung bình di chuyển trơn tru và chỉ số dao động để xây dựng một kênh dao động đa lớp và tạo ra các tín hiệu dài / ngắn rõ ràng. Nó thuộc thể loại chiến lược theo xu hướng. Chiến lược này kết hợp các chỉ số tổng hợp RSI, CCI, Stochastic và MA để xác định xu hướng thị trường tổng thể và khu vực mua quá mức / bán quá mức. Đây là một chiến lược xếp hạng đa yếu tố.

Nguyên tắc

  1. Tính toán trung bình trọng số của RSI, CCI và Stochastic để xây dựng một chỉ số dao động kết hợp được gọi là Magic;
  2. Áp dụng làm mịn theo hàm số nhân đến Magic nhiều lần để tạo ra hai đường được gọi là sampleMagicFast và sampleMagicSlow;
  3. sampleMagicFast đại diện cho đường EMA nhanh, sampleMagicSlow đại diện cho đường EMA chậm;
  4. Một tín hiệu mua được tạo ra khi sampleMagicFast vượt qua sampleMagicSlow;
  5. Một tín hiệu bán được tạo ra khi sampleMagicFast vượt qua dưới sampleMagicSlow;
  6. Tính toán hướng của thanh cuối cùng được lấy mẫu MagicFast so với thanh trước để xác định xu hướng hiện tại;
  7. Xác định các điểm vào và ra dựa trên hướng xu hướng và tình huống giao nhau giữa MagicFast và MagicSlow được lấy mẫu.

Ưu điểm

  1. Kết hợp nhiều chỉ số để xác định xu hướng thị trường tổng thể cải thiện độ chính xác tín hiệu;
  2. MA mịn lọc tiếng ồn hiệu quả;
  3. Các tín hiệu dao động nhiều lớp cung cấp hướng dẫn hoạt động rõ ràng;
  4. Có thể được cấu hình để theo xu hướng hoặc đảo ngược trung bình bằng cách kích hoạt / vô hiệu hóa bộ lọc xu hướng;
  5. Có thể tùy chỉnh sức mạnh mua quá mức / bán quá mức để linh hoạt.

Rủi ro

  1. Các đường cong quá mịn có thể gây ra việc thiếu các điểm vào tốt nhất;
  2. Cài đặt không chính xác khu vực mua quá mức/bán quá mức có thể giữ vị trí đóng quá lâu;
  3. Sự thất bại của một số yếu tố trong mô hình xếp hạng có thể làm suy yếu tín hiệu.

Giải pháp:

  1. Tối ưu hóa các thông số cho mức độ làm mịn thích hợp;
  2. Điều chỉnh cường độ khu vực mua quá mức / bán quá mức để giảm thời gian ở vị trí phẳng;
  3. Kiểm tra và cân nhắc từng chỉ số theo khả năng dự đoán của nó.

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

  1. Điều chỉnh động các tham số chỉ số dựa trên điều kiện thị trường;
  2. giới thiệu các phương pháp học máy để tự động tối ưu hóa các kết hợp chỉ số;
  3. Thêm các yếu tố như bộ lọc khối lượng và biến động vào tín hiệu đầu vào.

Kết luận

Chiến lược dao động cầu vồng kết hợp các tín hiệu từ nhiều chỉ số và sử dụng làm mịn theo cấp số nhân để cải thiện sự ổn định. Nó có thể được cấu hình cho cả thị trường xu hướng và bên cạnh, hoặc cho các sản phẩm cụ thể. Những cải tiến hơn nữa có thể được thực hiện bằng cách điều chỉnh tham số và mở rộng chỉ số.


// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © businessduck

//@version=5
strategy("Rainbow Oscillator [Strategy]", overlay=false, margin_long=100, margin_short=100, initial_capital = 2000)

bool trendFilter = input.bool(true, 'Use trend filter')
float w1 = input.float(0.33, 'RSI Weight', 0, 1, 0.01)
float w2 = input.float(0.33, 'CCI Weight', 0, 1, 0.01)
float w3 = input.float(0.33, 'Stoch Weight', 0, 1, 0.01)
int fastPeriod = input.int(16, 'Ocillograph Fast Period', 4, 60, 1)
int slowPeriod = input.int(22, 'Ocillograph Slow Period', 4, 60, 1)
int oscillographSamplePeriod = input.int(8, 'Oscillograph Samples Period', 1, 30, 1)
int oscillographSamplesCount = input.int(2, 'Oscillograph Samples Count', 0, 4, 1)
string oscillographMAType = input.string("RMA", "Oscillograph Samples Type", options = ["EMA", "SMA", "RMA", "WMA"])
int levelPeriod = input.int(26, 'Level Period', 2, 100)
int levelOffset = input.int(0, 'Level Offset', 0, 200, 10)
float redunant = input.float(0.5, 'Level Redunant', 0, 1, 0.01)
int levelSampleCount = input.int(2, 'Level Smooth Samples', 0, 4, 1)
string levelType = input.string("RMA", "Level MA type", options = ["EMA", "SMA", "RMA", "WMA"])

perc(current, prev) => ((current - prev) / prev) * 100

smooth(value, type, period) =>
    float ma = switch type
        "EMA" => ta.ema(value, period)
        "SMA" => ta.sma(value, period)
        "RMA" => ta.rma(value, period)
        "WMA" => ta.wma(value, period)
        =>
            runtime.error("No matching MA type found.")
            float(na)

getSample(value, samples, type, period) =>
    float ma = switch samples
        0 => value
        1 => smooth(value, type, period)
        2 => smooth(smooth(value, type, period), type, period)
        3 => smooth(smooth(smooth(value, type, period), type, period), type, period)
        4 => smooth(smooth(smooth(smooth(value, type, period), type, period), type, period), type, period)

float takeProfit = input.float(5, "% Take profit", 0.8, 100, step = 0.1)  / 100
float stopLoss = input.float(2, "% Stop Loss", 0.8, 100, step = 0.1) / 100
float magicFast = w2 * ta.cci(close, fastPeriod) + w1 * (ta.rsi(close, fastPeriod) - 50) + w3 * (ta.stoch(close, high, low, fastPeriod) - 50)
float magicSlow = w2 * ta.cci(close, slowPeriod) + w1 * (ta.rsi(close, slowPeriod) - 50) + w3 * (ta.stoch(close, high, low, slowPeriod) - 50)
float sampledMagicFast = getSample(magicFast, oscillographSamplesCount, oscillographMAType, oscillographSamplePeriod)
float sampledMagicSlow = getSample(magicSlow, oscillographSamplesCount, oscillographMAType, oscillographSamplePeriod)
float lastUpperValue = 0
float lastLowerValue = 0

if (magicFast > 0)
    lastUpperValue := math.max(magicFast, magicFast[1])
else 
    lastUpperValue := math.max(0, lastUpperValue[1]) * redunant

    
if (magicFast <= 0)
    lastLowerValue := math.min(magicFast, magicFast[1])
else
    lastLowerValue := math.min(0, lastLowerValue[1]) * redunant

float level1up = getSample( (magicFast >= 0 ? magicFast : lastUpperValue) / 4, levelSampleCount, levelType, levelPeriod) + levelOffset
float level2up = getSample( (magicFast >= 0 ? magicFast : lastUpperValue) / 2, levelSampleCount, levelType, levelPeriod) + levelOffset
float level3up = getSample( magicFast >= 0 ? magicFast : lastUpperValue, levelSampleCount, levelType, levelPeriod) + levelOffset
float level4up = getSample( (magicFast >= 0 ? magicFast : lastUpperValue) * 2, levelSampleCount, levelType, levelPeriod) + levelOffset

float level1low = getSample( (magicFast <= 0 ? magicFast : lastLowerValue) / 4, levelSampleCount, levelType, levelPeriod) - levelOffset
float level2low = getSample( (magicFast <= 0 ? magicFast : lastLowerValue) / 2, levelSampleCount, levelType, levelPeriod) - levelOffset
float level3low = getSample( magicFast <= 0 ? magicFast : lastLowerValue, levelSampleCount, levelType, levelPeriod) - levelOffset
float level4low = getSample( (magicFast <= 0 ? magicFast : lastLowerValue) * 2, levelSampleCount, levelType, levelPeriod) - levelOffset

var transparent = color.new(color.white, 100)
var overbough4Color = color.new(color.red, 75)
var overbough3Color = color.new(color.orange, 75)
var overbough2Color = color.new(color.yellow, 75)

var oversold4Color = color.new(color.teal, 75)
var oversold3Color = color.new(color.blue, 75)
var oversold2Color = color.new(color.aqua, 85)

upperPlotId1 = plot(level1up, 'Upper1', transparent)
upperPlotId2 = plot(level2up, 'Upper2', transparent)
upperPlotId3 = plot(level3up, 'Upper3', transparent)
upperPlotId4 = plot(level4up, 'Upper4', transparent)

fastColor = color.new(color.teal, 60)
slowColor = color.new(color.red, 60)
fastPlotId = plot(sampledMagicFast, 'fast', color = fastColor)
slowPlotId = plot(sampledMagicSlow, 'slow', color = slowColor)

lowerPlotId1 = plot(level1low, 'Lower1', transparent)
lowerPlotId2 = plot(level2low, 'Lower2', transparent)
lowerPlotId3 = plot(level3low, 'Lower3', transparent)
lowerPlotId4 = plot(level4low, 'Lower4', transparent)

fill(upperPlotId4, upperPlotId3, overbough4Color)
fill(upperPlotId3, upperPlotId2, overbough3Color)
fill(upperPlotId2, upperPlotId1, overbough2Color)

fill(lowerPlotId4, lowerPlotId3, oversold4Color)
fill(lowerPlotId3, lowerPlotId2, oversold3Color)
fill(lowerPlotId2, lowerPlotId1, oversold2Color)

upTrend = sampledMagicFast > sampledMagicFast[1]
buySignal = ((upTrend or not trendFilter) and ta.crossunder(sampledMagicSlow, sampledMagicFast)) ? sampledMagicSlow : na
sellSignal = ((not upTrend or not trendFilter) and ta.crossover(sampledMagicSlow, sampledMagicFast)) ? sampledMagicSlow : na
diff = sampledMagicSlow - sampledMagicFast

fill(fastPlotId, slowPlotId, upTrend ? fastColor : slowColor)
plot(buySignal, color = color.aqua, style = plot.style_circles, linewidth = 4)
plot(sellSignal, color = color.red, style = plot.style_circles, linewidth = 4)


// longCondition = upTrend != upTrend[1] and upTrend
long_take_level = strategy.position_avg_price * (1 + takeProfit)
long_stop_level = strategy.position_avg_price * (1 - stopLoss)

short_take_level = strategy.position_avg_price * (1 - takeProfit)
short_stop_level = strategy.position_avg_price * (1 + stopLoss)

strategy.close(id="Long", when=sellSignal, comment = "Exit")
strategy.close(id="Short", when=buySignal, comment = "Exit")

strategy.entry("Long", strategy.long, when=buySignal)
strategy.entry("Short", strategy.short, when=sellSignal)

strategy.exit("Take Profit/ Stop Loss","Long", stop=long_stop_level, limit=long_take_level)
strategy.exit("Take Profit/ Stop Loss","Short", stop=short_stop_level, limit=short_take_level)


// plot(long_stop_level, color=color.red, overlay=true)
// plot(long_take_level, color=color.green)


Thêm nữa