Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save wuuconix/728c7fa072bace4e8f33d5843c55b7d1 to your computer and use it in GitHub Desktop.
Save wuuconix/728c7fa072bace4e8f33d5843c55b7d1 to your computer and use it in GitHub Desktop.
1分钟实体突破-精确计时版-动量过滤
//@version=5
strategy("1分钟实体突破-精确计时版-动量过滤", overlay=true, process_orders_on_close=true)
adx_length = input.int(14, "ADX周期")
adx_threshold = input.int(20, "ADX阈值")
[_, _, adx] = ta.dmi(adx_length, adx_length)
adx_ok = adx > adx_threshold
// === 参数设置 ===
length_bb = input.int(20, "布林带周期")
mult = input.float(2.0, "布林带倍数")
ma_length = input.int(50, "均线周期")
use_trend_filter = input.bool(true, "趋势过滤")
trade_duration = input.int(10, "持仓时间(分钟)", minval=1)
use_rsi_filter = input.bool(true, "启用RSI过滤")
rsi_length = input.int(14, "RSI周期")
rsi_long = input.int(55, "做多RSI阈值")
rsi_short = input.int(45, "做空RSI阈值")
use_macd_filter = input.bool(true, "启用MACD过滤")
// === 指标计算 ===
basis = ta.sma(close, length_bb)
dev = mult * ta.stdev(close, length_bb)
upper = basis + dev
lower = basis - dev
ma = ta.sma(close, ma_length)
rsi = ta.rsi(close, rsi_length)
[macdLine, signalLine, histLine] = ta.macd(close, 12, 26, 9)
// === 信号条件 ===
body_break_upper = close > upper and open > upper[1]
body_break_lower = close < lower and open < lower[1]
trend_up = close > ma
trend_down = close < ma
rsi_long_ok = not use_rsi_filter or rsi > rsi_long
rsi_short_ok = not use_rsi_filter or rsi < rsi_short
macd_long_ok = not use_macd_filter or histLine > 0
macd_short_ok = not use_macd_filter or histLine < 0
// === 交易逻辑 ===
// 用plotshape标记信号点位
plotshape(body_break_upper and (not use_trend_filter or trend_up) and rsi_long_ok and macd_long_ok and adx_ok, title="↑突破", style=shape.triangleup, location=location.belowbar, color=color.green, size=size.small)
plotshape(body_break_lower and (not use_trend_filter or trend_down) and rsi_short_ok and macd_short_ok and adx_ok, title="↓突破", style=shape.triangledown, location=location.abovebar, color=color.red, size=size.small)
// === 可视化 ===
plot(basis, "中线", color=color.orange)
plot(upper, "上轨", color=color.green)
plot(lower, "下轨", color=color.red)
plot(ma, "均线", color=color.blue)
plot(rsi, "RSI", color=color.purple, linewidth=1, title="RSI")
hline(rsi_long, "RSI多阈值", color=color.green)
hline(rsi_short, "RSI空阈值", color=color.red)
plot(adx, "ADX", color=color.fuchsia, linewidth=1, title="ADX")
hline(adx_threshold, "ADX阈值", color=color.fuchsia)
@wuuconix
Copy link
Author

统计胜率

//@version=5
strategy("1分钟实体突破-精确计时版-动量过滤", overlay=true, process_orders_on_close=true)

adx_length = input.int(14, "ADX周期")
adx_threshold = input.int(20, "ADX阈值")
[_, _, adx] = ta.dmi(adx_length, adx_length)
adx_ok = adx > adx_threshold

// === 参数设置 ===
length_bb = input.int(20, "布林带周期")
mult = input.float(2.0, "布林带倍数")
ma_length = input.int(50, "均线周期")
use_trend_filter = input.bool(true, "趋势过滤")
trade_duration = input.int(10, "持仓时间(分钟)", minval=1)
use_rsi_filter = input.bool(true, "启用RSI过滤")
rsi_length = input.int(14, "RSI周期")
rsi_long = input.int(55, "做多RSI阈值")
rsi_short = input.int(45, "做空RSI阈值")
use_macd_filter = input.bool(true, "启用MACD过滤")
stats_period = input.string("1天", "统计时段", options=["1小时", "4小时", "6小时", "12小时", "1天", "3天", "7天"])

// === 指标计算 ===
basis = ta.sma(close, length_bb)
dev = mult * ta.stdev(close, length_bb)
upper = basis + dev
lower = basis - dev
ma = ta.sma(close, ma_length)
rsi = ta.rsi(close, rsi_length)
[macdLine, signalLine, histLine] = ta.macd(close, 12, 26, 9)

// === 信号条件 ===
body_break_upper = close > upper and open > upper[1]
body_break_lower = close < lower and open < lower[1]
trend_up = close > ma
trend_down = close < ma
rsi_long_ok = not use_rsi_filter or rsi > rsi_long
rsi_short_ok = not use_rsi_filter or rsi < rsi_short
macd_long_ok = not use_macd_filter or histLine > 0
macd_short_ok = not use_macd_filter or histLine < 0

// === 交易逻辑 ===
// 用plotshape标记信号点位
plotshape(body_break_upper and (not use_trend_filter or trend_up) and rsi_long_ok and macd_long_ok and adx_ok, title="↑突破", style=shape.triangleup, location=location.belowbar, color=color.green, size=size.small)
plotshape(body_break_lower and (not use_trend_filter or trend_down) and rsi_short_ok and macd_short_ok and adx_ok, title="↓突破", style=shape.triangledown, location=location.abovebar, color=color.red, size=size.small)

// === 可视化 ===
plot(basis, "中线", color=color.orange)
plot(upper, "上轨", color=color.green)
plot(lower, "下轨", color=color.red)
plot(ma, "均线", color=color.blue)
plot(rsi, "RSI", color=color.purple, linewidth=1, title="RSI")
hline(rsi_long, "RSI多阈值", color=color.green)
hline(rsi_short, "RSI空阈值", color=color.red)
plot(adx, "ADX", color=color.fuchsia, linewidth=1, title="ADX")
hline(adx_threshold, "ADX阈值", color=color.fuchsia)


// === 币安10分钟事件合约胜率统计 ===
var array<float> all_signal_prices = array.new<float>()
var array<string> all_signal_types = array.new<string>()
var array<int> all_signal_times = array.new<int>()
var array<bool> all_signal_results = array.new<bool>()
var array<float> pending_prices = array.new<float>()
var array<string> pending_types = array.new<string>()
var array<int> pending_bars = array.new<int>()
var array<int> pending_times = array.new<int>()

// 获取统计时间窗口(毫秒)
get_time_window() =>
    switch stats_period
        "1小时" => 1 * 60 * 60 * 1000
        "4小时" => 4 * 60 * 60 * 1000
        "6小时" => 6 * 60 * 60 * 1000
        "12小时" => 12 * 60 * 60 * 1000
        "1天" => 24 * 60 * 60 * 1000
        "3天" => 3 * 24 * 60 * 60 * 1000
        "7天" => 7 * 24 * 60 * 60 * 1000

// 定义信号
long_signal = body_break_upper and (not use_trend_filter or trend_up) and rsi_long_ok and macd_long_ok and adx_ok
short_signal = body_break_lower and (not use_trend_filter or trend_down) and rsi_short_ok and macd_short_ok and adx_ok

// 记录新信号
if long_signal
    array.push(pending_prices, close)
    array.push(pending_types, "LONG")
    array.push(pending_bars, bar_index)
    array.push(pending_times, math.round(time))

if short_signal
    array.push(pending_prices, close)
    array.push(pending_types, "SHORT")
    array.push(pending_bars, bar_index)
    array.push(pending_times, math.round(time))

// 检查10分钟后的结果
if array.size(pending_bars) > 0
    for i = array.size(pending_bars) - 1 to 0
        signal_bar = array.get(pending_bars, i)
        if bar_index >= signal_bar + 10  // 10分钟后
            signal_price = array.get(pending_prices, i)
            signal_type = array.get(pending_types, i)
            signal_time = array.get(pending_times, i)
            
            // 判断胜负
            is_win = false
            if signal_type == "LONG"
                is_win := close > signal_price
            else if signal_type == "SHORT"
                is_win := close < signal_price
            
            // 保存到历史记录
            array.push(all_signal_prices, signal_price)
            array.push(all_signal_types, signal_type)
            array.push(all_signal_times, signal_time)
            array.push(all_signal_results, is_win)
            
            // 删除已处理的信号
            array.remove(pending_prices, i)
            array.remove(pending_types, i)
            array.remove(pending_bars, i)
            array.remove(pending_times, i)

// 统计指定时段内的胜率
time_window = get_time_window()
current_time = math.round(time)
total_count = 0
win_count = 0

if array.size(all_signal_times) > 0
    for i = 0 to array.size(all_signal_times) - 1
        signal_time = array.get(all_signal_times, i)
        signal_result = array.get(all_signal_results, i)
        
        // 检查是否在统计时间窗口内
        in_window = (current_time - signal_time <= time_window)
        
        if in_window
            total_count += 1
            if signal_result
                win_count += 1

// 计算胜率
win_rate = total_count > 0 ? (win_count * 100.0 / total_count) : 0.0

// 显示胜率
var label info_label = na
if barstate.islast
    label.delete(info_label)
    period_text = stats_period
    info_text = period_text + "胜率: " + str.tostring(win_rate, "#.##") + "%\n胜:" + str.tostring(win_count) + " 总:" + str.tostring(total_count)
    info_label := label.new(bar_index, high, info_text, 
                           style=label.style_label_down, 
                           color=color.new(color.blue, 20), 
                           textcolor=color.white, 
                           size=size.normal)

@wuuconix
Copy link
Author

default.mp4

@wuuconix
Copy link
Author

default.mp4

@wuuconix
Copy link
Author

wuuconix commented Aug 11, 2025

1
2
3

5

@wuuconix
Copy link
Author

f4ed849448a76d25e1f0a4dfe2a38af

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment