-
-
Save wuuconix/8042807072605dd7a8563eebf85cdbc1 to your computer and use it in GitHub Desktop.
1分钟实体突破
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//@version=5 | |
strategy("1分钟实体突破-精确计时版", overlay=true, process_orders_on_close=true) | |
// === 参数设置 === | |
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) | |
// === 指标计算 === | |
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) | |
// === 信号条件 === | |
// 实体突破定义:收盘价突破(忽略上下影线) | |
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 | |
// === 交易逻辑 === | |
var int entry_bar_index = na // 记录入场K线索引 | |
var int entry_time = na // 精确入场时间戳 | |
// 多单条件(K线收盘后检查) | |
if (body_break_upper and (not use_trend_filter or trend_up) and strategy.position_size <= 0) | |
strategy.entry("Long", strategy.long) | |
alert("Long " + str.tostring(close), alert.freq_once_per_bar_close) | |
entry_bar_index := bar_index | |
entry_time := time | |
// 空单条件(K线收盘后检查) | |
if (body_break_lower and (not use_trend_filter or trend_down) and strategy.position_size >= 0) | |
strategy.entry("Short", strategy.short) | |
alert("Short " + str.tostring(close), alert.freq_once_per_bar_close) | |
entry_bar_index := bar_index | |
entry_time := time | |
// === 平仓逻辑 === | |
// 方式1:精确时间控制(推荐) | |
// if (not na(entry_time) and (time - entry_time) >= trade_duration*60*1000) | |
// strategy.close_all() | |
// entry_time := na | |
// entry_bar_index := na | |
// 方式2:K线数量控制(备选) | |
// if (not na(entry_bar_index) and (bar_index - entry_bar_index) >= trade_duration | |
// strategy.close_all() | |
// entry_bar_index := na | |
// === 可视化 === | |
plot(basis, "中线", color=color.orange) | |
plot(upper, "上轨", color=color.green) | |
plot(lower, "下轨", color=color.red) | |
plot(ma, "均线", color=color.blue) | |
// 标记入场点 | |
// plotshape(body_break_upper and strategy.position_size <= 0, "↑突破", shape.triangleup, location.belowbar, color.green, size=size.small) | |
// plotshape(body_break_lower and strategy.position_size >= 0, "↓突破", shape.triangledown, location.abovebar, color.red, size=size.small) |
计算胜率:
//@version=5
indicator("事件合约胜率统计 (近1天修正版)", overlay=true)
length_bb = input.int(20, "布林带周期")
mult = input.float(2.0, "布林带倍数")
ma_length = input.int(50, "均线周期")
use_trend_filter = input.bool(true, "趋势过滤")
hold_minutes = 10
time_window_ms = 7 * 24 * 60 * 60 * 1000 // 1天
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)
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
long_signal = body_break_upper and (not use_trend_filter or trend_up)
short_signal = body_break_lower and (not use_trend_filter or trend_down)
// === 数组
var float[] entry_prices = array.new_float()
var int[] entry_bar_indices = array.new_int()
var string[] entry_types = array.new_string()
var int[] entry_times = array.new_int()
var int[] remove_indexes = array.new_int()
var int closed_signals = 0
var int win_count = 0
// === 新信号记录
if long_signal or short_signal
array.push(entry_prices, close)
array.push(entry_bar_indices, bar_index + hold_minutes)
array.push(entry_types, long_signal ? "Long" : "Short")
array.push(entry_times, time)
// === 统计
if array.size(entry_prices) > 0
for i = 0 to array.size(entry_prices) - 1
target_bar_index = array.get(entry_bar_indices, i)
signal_time = array.get(entry_times, i)
if bar_index >= target_bar_index
in_period = (timenow - signal_time) <= time_window_ms
if in_period
closed_signals := closed_signals + 1
entry_price = array.get(entry_prices, i)
entry_type = array.get(entry_types, i)
if entry_type == "Long" and close > entry_price
win_count := win_count + 1
if entry_type == "Short" and close < entry_price
win_count := win_count + 1
array.push(remove_indexes, i)
// === 倒序删除
while array.size(remove_indexes) > 0
j = array.size(remove_indexes) - 1
remove_index = array.get(remove_indexes, j)
array.remove(entry_prices, remove_index)
array.remove(entry_bar_indices, remove_index)
array.remove(entry_types, remove_index)
array.remove(entry_times, remove_index)
array.remove(remove_indexes, j)
// === 胜率
win_rate = closed_signals > 0 ? (win_count / closed_signals) * 100 : na
// === 图表标记
plotshape(long_signal, title="Long", location=location.belowbar, color=color.green, style=shape.triangleup, size=size.small)
plotshape(short_signal, title="Short", location=location.abovebar, color=color.red, style=shape.triangledown, size=size.small)
plot(basis, "中线", color=color.orange)
plot(upper, "上轨", color=color.green)
plot(lower, "下轨", color=color.red)
plot(ma, "均线", color=color.blue)
// === 胜率标签
var label win_label = na
if barstate.islast and not na(win_rate)
label.delete(win_label)
win_label := label.new(bar_index, high, "近1天胜率: " + str.tostring(win_rate, "#.##") + "%", style=label.style_label_down, color=color.new(color.blue, 0), textcolor=color.white)
胜率统计优化
//@version=5
strategy("1分钟实体突破-精确计时版", overlay=true, process_orders_on_close=true)
// === 参数设置 ===
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)
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)
// === 信号条件 ===
// 实体突破定义:收盘价突破(忽略上下影线)
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
// === 交易逻辑 ===
var int entry_bar_index = na // 记录入场K线索引
var int entry_time = na // 精确入场时间戳
// 多单条件(K线收盘后检查)
if (body_break_upper and (not use_trend_filter or trend_up))
// strategy.entry("Long", strategy.long)
alert("Long " + str.tostring(close), alert.freq_once_per_bar_close)
entry_bar_index := bar_index
entry_time := time
// 空单条件(K线收盘后检查)
if (body_break_lower and (not use_trend_filter or trend_down))
// strategy.entry("Short", strategy.short)
alert("Short " + str.tostring(close), alert.freq_once_per_bar_close)
entry_bar_index := bar_index
entry_time := time
// === 可视化 ===
plot(basis, "中线", color=color.orange)
plot(upper, "上轨", color=color.green)
plot(lower, "下轨", color=color.red)
plot(ma, "均线", color=color.blue)
// 标记入场点
plotshape(body_break_upper and (not use_trend_filter or trend_up), "↑突破", shape.triangleup, location.belowbar, color.green, size=size.small)
plotshape(body_break_lower and (not use_trend_filter or trend_down), "↓突破", shape.triangledown, location.abovebar, color.red, size=size.small)
// === 币安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)
short_signal = body_break_lower and (not use_trend_filter or trend_down)
// 记录新信号
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)
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
允许多比Long和Short,不下单,只标记。