Chiến lược giao dịch xu hướng động lượng nến dựa trên các chỉ số định lượng

CEI ADX RSI MACD VOLUME SMA
Ngày tạo: 2025-02-21 13:23:51 sửa đổi lần cuối: 2025-02-21 13:23:51
sao chép: 1 Số nhấp chuột: 361
2
tập trung vào
319
Người theo dõi

Chiến lược giao dịch xu hướng động lượng nến dựa trên các chỉ số định lượng Chiến lược giao dịch xu hướng động lượng nến dựa trên các chỉ số định lượng

Tổng quan

Chiến lược này dựa trên phân tích hình đồ thị về cảm xúc thị trường, định lượng tâm lý thị trường thông qua ba dao động cốt lõi: dao động do dự, dao động sợ hãi và dao động tham lam. Chiến lược này tích hợp các chỉ số động lực và xu hướng, đồng thời kết hợp xác nhận giao dịch để xây dựng một hệ thống giao dịch hoàn chỉnh. Chiến lược này phù hợp cho các nhà giao dịch muốn xác định cơ hội giao dịch có khả năng cao thông qua phân tích cảm xúc thị trường.

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

Cốt lõi của chiến lược là xây dựng ba rung động cảm xúc bằng cách phân tích các hình dạng khác nhau của photon:

  1. Vibration oscillator - đo lường sự không chắc chắn của thị trường thông qua hình dạng hình chữ thập và hình xoáy
  2. Máy rung sợ hãi - theo dõi cảm xúc vô nghĩa thông qua sao băng, dây treo và hình thức nuốt chửng giảm giá
  3. Động cơ tham lam - Chẩn đoán cảm xúc đa đầu bằng tia nắng, dây thừng, ngắm ngấu nghiến ngấu nghiến và ba người lính trắng

Các giá trị trung bình của ba dao động này tạo thành chỉ số tâm trạng thăng hoa ((CEI)). Khi CEI vượt qua các ngưỡng khác nhau, nó sẽ kích hoạt tín hiệu giao dịch đa thùng và xác nhận thông qua khối lượng giao dịch.

Lợi thế chiến lược

  1. Phân tích cảm xúc có hệ thống - chuyển đổi phân tích chủ quan thành chỉ số khách quan thông qua hình ảnh đồ thị định lượng
  2. Quản lý rủi ro tốt - bao gồm các cơ chế như thời gian giữ vị trí tối đa, dừng lỗ và thời gian nguội lạnh
  3. Cơ chế phục hồi linh hoạt - khi giao dịch bị thua lỗ, chiến lược sẽ cố gắng phục hồi bằng cách phá vỡ điểm cân bằng
  4. Khả năng ứng dụng trên nhiều thị trường - có thể áp dụng cho nhiều thị trường như cổ phiếu, ngoại hối và tiền điện tử
  5. Tín hiệu đáng tin cậy cao - tăng độ chính xác thông qua xác nhận khối lượng giao dịch và xác minh nhiều chỉ số kỹ thuật

Rủi ro chiến lược

  1. Nhận thức tham số - thiết lập các loại ngưỡng cần được thử nghiệm và tối ưu hóa đầy đủ
  2. Tùy thuộc vào môi trường thị trường - có thể tạo ra tín hiệu sai trong thị trường bất ổn
  3. Rủi ro trượt - rủi ro thực hiện có thể xảy ra trong thị trường ít thanh khoản
  4. Rủi ro giao dịch quá mức - Cần thiết lập thời gian nguội để tránh giao dịch thường xuyên
  5. Rủi ro hệ thống - có thể chịu tổn thất lớn trong các sự kiện thị trường lớn

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

  1. Động lực giảm giá - tự động điều chỉnh các loại giảm giá theo biến động của thị trường
  2. Phân loại tình trạng thị trường - cơ chế nhận diện thị trường tăng xu hướng và biến động
  3. Tối ưu hóa học máy - Tối ưu hóa các tham số sử dụng thuật toán học máy
  4. Tăng cường quản lý rủi ro - thêm mô-đun quản lý tài chính và kiểm soát vị trí
  5. Bộ lọc tín hiệu - tích hợp thêm các chỉ số kỹ thuật để lọc tín hiệu giả

Tóm tắt

Đây là một chiến lược sáng tạo kết hợp phân tích kỹ thuật với giao dịch định lượng. Bằng cách phân tích cảm xúc có hệ thống và quản lý rủi ro nghiêm ngặt, chiến lược này có thể cung cấp tín hiệu giao dịch đáng tin cậy cho các nhà giao dịch. Mặc dù có một số không gian tối ưu hóa, nhưng khung cơ bản của chiến lược là vững chắc, phù hợp cho việc phát triển và ứng dụng thực tế hơn nữa.

Mã nguồn chiến lược
/*backtest
start: 2024-03-09 18:40:00
end: 2025-02-19 08:00:00
period: 1d
basePeriod: 1d
exchanges: [{"eid":"Binance","currency":"SOL_USDT"}]
*/

//@version=6
strategy("Candle Emotion Index Strategy", shorttitle="CEI Strategy", overlay=true)

// User Inputs
length = input.int(14, title="Lookback Period", minval=1)
dojiThreshold = input.float(0.1, title="Doji Threshold", minval=0.01, maxval=0.5)
spinningTopThreshold = input.float(0.3, title="Spinning Top Threshold", minval=0.1, maxval=0.5)
shootingStarThreshold = input.float(0.5, title="Shooting Star Threshold", minval=0.1, maxval=1.0)
hangingManThreshold = input.float(0.5, title="Hanging Man Threshold", minval=0.1, maxval=1.0)
engulfingThreshold = input.float(0.5, title="Engulfing Threshold", minval=0.1, maxval=1.0)
marubozuThreshold = input.float(0.9, title="Marubozu Threshold", minval=0.5, maxval=1.0)
hammerThreshold = input.float(0.5, title="Hammer Threshold", minval=0.1, maxval=1.0)
threeWhiteSoldiersThreshold = input.float(0.5, title="Three White Soldiers Threshold", minval=0.1, maxval=1.0)

// Volume Multiplier Input
volumeMultiplier = input.float(1.5, title="Volume Multiplier", minval=1.0)

// Cooldown Period Input
cooldownPeriod = input.int(10, title="Cooldown Period (Candles)", minval=1)

// Maximum Holding Period Inputs
maxHoldingPeriod = input.int(20, title="Maximum Holding Period (Candles)", minval=1)
lossHoldingPeriod = input.int(10, title="Loss Exit Holding Period (Candles)", minval=1)
lossThreshold = input.float(0.02, title="Loss Threshold (as % of Entry Price)", minval=0.01, maxval=1.0)

// --- Indecision Oscillator Functions ---
isDoji(open, close, high, low, threshold) =>
    bodySize = math.abs(close - open)
    rangeSize = high - low
    bodySize / rangeSize < threshold

isSpinningTop(open, close, high, low, threshold) =>
    bodySize = math.abs(close - open)
    rangeSize = high - low
    bodySize / rangeSize < threshold and bodySize / rangeSize >= dojiThreshold

indecisionOscillator() =>
    var float dojiScore = 0.0
    var float spinningTopScore = 0.0
    for i = 1 to length
        if isDoji(open[i], close[i], high[i], low[i], dojiThreshold)
            dojiScore := dojiScore + 1.0
        if isSpinningTop(open[i], close[i], high[i], low[i], spinningTopThreshold)
            spinningTopScore := spinningTopScore + 1.0
    dojiScore := dojiScore / length
    spinningTopScore := spinningTopScore / length
    (dojiScore + spinningTopScore) / 2

// --- Fear Oscillator Functions ---
isShootingStar(open, close, high, low, threshold) =>
    bodySize = math.abs(close - open)
    upperWick = high - math.max(open, close)
    lowerWick = math.min(open, close) - low
    upperWick / bodySize > threshold and lowerWick < bodySize

isHangingMan(open, close, high, low, threshold) =>
    bodySize = math.abs(close - open)
    upperWick = high - math.max(open, close)
    lowerWick = math.min(open, close) - low
    lowerWick / bodySize > threshold and upperWick < bodySize

isBearishEngulfing(open, close, openPrev, closePrev, threshold) =>
    bodySize = math.abs(close - open)
    prevBodySize = math.abs(closePrev - openPrev)
    close < openPrev and open > closePrev and bodySize / prevBodySize > threshold

fearOscillator() =>
    var float shootingStarScore = 0.0
    var float hangingManScore = 0.0
    var float engulfingScore = 0.0
    for i = 1 to length
        if isShootingStar(open[i], close[i], high[i], low[i], shootingStarThreshold)
            shootingStarScore := shootingStarScore + 1.0
        if isHangingMan(open[i], close[i], high[i], low[i], hangingManThreshold)
            hangingManScore := hangingManScore + 1.0
        if isBearishEngulfing(open[i], close[i], open[i+1], close[i+1], engulfingThreshold)
            engulfingScore := engulfingScore + 1.0
    shootingStarScore := shootingStarScore / length
    hangingManScore := hangingManScore / length
    engulfingScore := engulfingScore / length
    (shootingStarScore + hangingManScore + engulfingScore) / 3

// --- Greed Oscillator Functions ---
isMarubozu(open, close, high, low, threshold) =>
    bodySize = math.abs(close - open)
    totalRange = high - low
    bodySize / totalRange > threshold

isHammer(open, close, high, low, threshold) =>
    bodySize = math.abs(close - open)
    lowerWick = math.min(open, close) - low
    upperWick = high - math.max(open, close)
    lowerWick / bodySize > threshold and upperWick < bodySize

isBullishEngulfing(open, close, openPrev, closePrev, threshold) =>
    bodySize = math.abs(close - open)
    prevBodySize = math.abs(closePrev - openPrev)
    close > openPrev and open < closePrev and bodySize / prevBodySize > threshold

isThreeWhiteSoldiers(open, close, openPrev, closePrev, openPrev2, closePrev2, threshold) =>
    close > open and closePrev > openPrev and closePrev2 > openPrev2 and close > closePrev and closePrev > closePrev2

greedOscillator() =>
    var float marubozuScore = 0.0
    var float hammerScore = 0.0
    var float engulfingScore = 0.0
    var float soldiersScore = 0.0
    for i = 1 to length
        if isMarubozu(open[i], close[i], high[i], low[i], marubozuThreshold)
            marubozuScore := marubozuScore + 1.0
        if isHammer(open[i], close[i], high[i], low[i], hammerThreshold)
            hammerScore := hammerScore + 1.0
        if isBullishEngulfing(open[i], close[i], open[i+1], close[i+1], engulfingThreshold)
            engulfingScore := engulfingScore + 1.0
        if isThreeWhiteSoldiers(open[i], close[i], open[i+1], close[i+1], open[i+2], close[i+2], threeWhiteSoldiersThreshold)
            soldiersScore := soldiersScore + 1.0
    marubozuScore := marubozuScore / length
    hammerScore := hammerScore / length
    engulfingScore := engulfingScore / length
    soldiersScore := soldiersScore / length
    (marubozuScore + hammerScore + engulfingScore + soldiersScore) / 4

// --- Final Calculations ---
indecision = indecisionOscillator()
fear = fearOscillator()
greed = greedOscillator()

// Calculate the average of the three oscillators
averageOscillator = (indecision + fear + greed) / 3

// --- Combined Strategy Logic ---
var float entryPriceLong = na
var float entryPriceShort = na
var int holdingPeriodLong = 0
var int holdingPeriodShort = 0
var int cooldownCounter = 0

// Buy Signal Logic for Long and Short
longBuySignal = ta.crossover(averageOscillator, 0.1)
shortBuySignal = ta.crossover(averageOscillator, 0.2)

// Calculate average volume over the lookback period
avgVolume = ta.sma(volume, length)

// Take Profit Conditions
longTakeProfitCondition = close > open and volume > avgVolume * volumeMultiplier
shortTakeProfitCondition = close < open and volume > avgVolume * volumeMultiplier

// Buy Logic for Long Positions
if longBuySignal and strategy.position_size == 0 and cooldownCounter <= 0
    entryPriceLong := close
    strategy.entry("Long Entry", strategy.long)
    cooldownCounter := cooldownPeriod
    holdingPeriodLong := 0

// Increment holding period if in a long position
if strategy.position_size > 0
    holdingPeriodLong := holdingPeriodLong + 1

// Sell Logic for Long Positions
if longTakeProfitCondition and strategy.position_size > 0 and close > entryPriceLong
    strategy.close_all()
    cooldownCounter := cooldownPeriod

if holdingPeriodLong >= maxHoldingPeriod and strategy.position_size > 0 and close >= entryPriceLong
    strategy.close_all()
    cooldownCounter := cooldownPeriod

if holdingPeriodLong >= lossHoldingPeriod and strategy.position_size > 0 and close < entryPriceLong * (1 - lossThreshold)
    strategy.close_all()
    cooldownCounter := cooldownPeriod

// Short Logic for Short Positions
if shortBuySignal and strategy.position_size == 0 and cooldownCounter <= 0
    entryPriceShort := close
    strategy.entry("Short Entry", strategy.short)
    cooldownCounter := cooldownPeriod
    holdingPeriodShort := 0

// Increment holding period if in a short position
if strategy.position_size < 0
    holdingPeriodShort := holdingPeriodShort + 1

// Cover Logic for Short Positions
if shortTakeProfitCondition and strategy.position_size < 0 and close < entryPriceShort
    strategy.close_all()
    cooldownCounter := cooldownPeriod

if holdingPeriodShort >= maxHoldingPeriod and strategy.position_size < 0 and close <= entryPriceShort
    strategy.close_all()
    cooldownCounter := cooldownPeriod

if holdingPeriodShort >= lossHoldingPeriod and strategy.position_size < 0 and close > entryPriceShort * (1 + lossThreshold)
    strategy.close_all()
    cooldownCounter := cooldownPeriod

// Decrement the cooldown counter each candle
if cooldownCounter > 0
    cooldownCounter := cooldownCounter - 1