up
This commit is contained in:
399
参考/Swing Failure Pattern.pine
Normal file
399
参考/Swing Failure Pattern.pine
Normal file
@@ -0,0 +1,399 @@
|
||||
// This work is licensed under a Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0) https://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||
// © LuxAlgo
|
||||
|
||||
//@version=5
|
||||
indicator( 'SwingFailurePattern [LuxAlgo]', 'LuxAlgo - Swing Failure Pattern', max_labels_count = 500, max_lines_count = 500, max_boxes_count = 500, overlay = true)
|
||||
//---------------------------------------------------------------------------------------------------------------------}
|
||||
//Settings
|
||||
//---------------------------------------------------------------------------------------------------------------------{
|
||||
sp = ' '
|
||||
len = input.int ( 5 , 'Swings' , minval= 1 )
|
||||
bull = input.bool ( true , 'Bullish SFP' )
|
||||
bear = input.bool ( true , 'Bearish SFP' )
|
||||
|
||||
iVal = input.string ('None', 'Validation'+sp+ ' ', group='Volume Validation'
|
||||
, options = ['Volume outside swing < Threshold' ,'Volume outside swing > Threshold','None'])
|
||||
percent = input.float (25, 'Volume Threshold %' , inline='valy', group='Volume Validation'
|
||||
, tooltip = '% of Total Volume' , minval= 0 , maxval=100 )
|
||||
auto = input.bool (true, '' , inline='auto', group='Volume Validation' )
|
||||
mlt = input.int (50 , ' Auto' + sp , inline='auto', group='Volume Validation' )
|
||||
res = input.timeframe('1' , sp +' LTF' + sp +' ', inline='ltf' , group='Volume Validation' )
|
||||
prem = input.bool (false ,' Premium' , group='Volume Validation'
|
||||
, tooltip = 'Premium Plan or higher' )
|
||||
showDash = input.bool (true , 'Show Dashboard' , group= 'Dashboard' )
|
||||
dashLoc = input.string ( 'Top Right' , 'Location'
|
||||
, options = ['Top Right', 'Bottom Right', 'Bottom Left'] , group= 'Dashboard' )
|
||||
textSize = input.string ( 'Normal' , 'Size'
|
||||
, options = ['Tiny', 'Small', 'Normal'] , group= 'Dashboard' )
|
||||
dSwingLine = input.bool (true , 'Swing Lines' , group= 'Style' )
|
||||
dOpposLine = input.bool (true , 'Confirmation Lines' , group= 'Style' )
|
||||
dSFP_Line = input.bool (true , 'Swing Failure Wick' , group= 'Style' )
|
||||
dSFP_Label = input.bool (true , 'Swing Failure Label' , group= 'Style' )
|
||||
showAlerts = input.bool (true , 'Show Alert Markers' , group= 'Style' )
|
||||
alertSize = input.string ('Normal', 'Alert Marker Size' , group= 'Style'
|
||||
, options = ['Small', 'Normal', 'Large'] )
|
||||
colBl = input.color (#089981 , 'Lines / Labels' , inline='lin' , group= 'Style' )
|
||||
colBr = input.color (#f23645 , '' , inline='lin' , group= 'Style'
|
||||
, tooltip = 'Bullish/Bearish' )
|
||||
colBl2 = input.color (#08998180, 'SFP Wicks ', inline='wic' , group= 'Style' )
|
||||
colBr2 = input.color (#f2364580, '' , inline='wic' , group= 'Style'
|
||||
, tooltip = 'Wick outside Swing, Bullish/Bearish' )
|
||||
|
||||
//-----------------------------------------------------------------------------}
|
||||
//UDT
|
||||
//-----------------------------------------------------------------------------{
|
||||
type piv
|
||||
float swing_prc // price
|
||||
int swing_bix // bar_index
|
||||
float oppos_prc // price
|
||||
int oppos_bix // bar_index
|
||||
bool active
|
||||
bool confirmed
|
||||
line swing_line
|
||||
line oppos_line
|
||||
line wicky_line
|
||||
label wicky_label
|
||||
|
||||
type swing
|
||||
int bix
|
||||
float prc
|
||||
|
||||
//-----------------------------------------------------------------------------}
|
||||
//Variables
|
||||
//-----------------------------------------------------------------------------{
|
||||
n = bar_index
|
||||
INV = color(na)
|
||||
FGc = chart.fg_color
|
||||
|
||||
table_position = dashLoc == 'Bottom Left' ? position.bottom_left
|
||||
: dashLoc == 'Top Right' ? position.top_right
|
||||
: position.bottom_right
|
||||
|
||||
table_size = textSize == 'Tiny' ? size.tiny
|
||||
: textSize == 'Small' ? size.small
|
||||
: size.normal
|
||||
|
||||
alert_marker_size = alertSize == 'Small' ? size.small
|
||||
: alertSize == 'Large' ? size.large
|
||||
: size.normal
|
||||
|
||||
var tb = table.new(table_position, 2, 3
|
||||
, bgcolor = #1e222d
|
||||
, border_color = #373a46
|
||||
, border_width = 1
|
||||
, frame_color = #373a46
|
||||
, frame_width = 1)
|
||||
|
||||
var swing swingH = swing.new()
|
||||
var swing swingL = swing.new()
|
||||
var piv pivH = piv.new()
|
||||
var piv pivL = piv.new()
|
||||
|
||||
validate = iVal != 'None'
|
||||
valHigher= iVal == 'Volume outside swing > Threshold'
|
||||
valLower = iVal == 'Volume outside swing < Threshold'
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------}
|
||||
//Method
|
||||
//---------------------------------------------------------------------------------------------------------------------{
|
||||
method n(float piv) => bool out = not na(piv)
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------}
|
||||
//Execution
|
||||
//---------------------------------------------------------------------------------------------------------------------{
|
||||
tfS = timeframe.in_seconds( res )
|
||||
tfC = timeframe.in_seconds(timeframe.period)
|
||||
rs = auto ? tfC / mlt : tfS
|
||||
if not validate
|
||||
res := timeframe.period
|
||||
else
|
||||
rs := prem ? rs : math.max(60, rs)
|
||||
res := timeframe.from_seconds(math.min(tfC, rs))
|
||||
|
||||
ph = ta.pivothigh(len, 1)
|
||||
pl = ta.pivotlow (len, 1)
|
||||
|
||||
[ltf_close, ltf_volume] = request.security_lower_tf(syminfo.tickerid, res, [close, volume])
|
||||
|
||||
ltf_size = ltf_close.size()
|
||||
|
||||
if validate
|
||||
if ltf_size > 0 and ltf_size[1] == 0
|
||||
line.new(n, close, n, close + syminfo.mintick, color=color.silver, style=line.style_dotted, extend=extend.both)
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------}
|
||||
//Bearish Pattern
|
||||
//---------------------------------------------------------------------------------------------------------------------{
|
||||
if bear
|
||||
|
||||
if ph.n()
|
||||
swingH.bix := n-1
|
||||
swingH.prc := ph
|
||||
|
||||
sw = swingH.prc
|
||||
bx = swingH.bix
|
||||
if high > sw
|
||||
and open < sw
|
||||
and close < sw
|
||||
valid = true
|
||||
if validate
|
||||
if ltf_close.size() > 0
|
||||
outsideVolume = 0.
|
||||
totalVolume = ltf_volume.sum()
|
||||
for j = 0 to ltf_close.size() -1
|
||||
if ltf_close.get(j) > sw
|
||||
outsideVolume += ltf_volume.get(j)
|
||||
if (valHigher ? 100 / totalVolume * outsideVolume < percent
|
||||
: 100 / totalVolume * outsideVolume > percent
|
||||
)
|
||||
valid := false
|
||||
|
||||
//if valid
|
||||
// label.new(n, high, text=str.format("Total Volume: {0}\nWick Volume: {1}", totalVolume, outsideVolume))
|
||||
|
||||
if valid
|
||||
|
||||
opposL = sw
|
||||
opposB = n
|
||||
|
||||
for i = 1 to n - bx -1
|
||||
if low [i] < opposL
|
||||
opposL := low [i]
|
||||
opposB := n - i
|
||||
|
||||
if not pivH.confirmed
|
||||
pivH.swing_line .delete()
|
||||
pivH.oppos_line .delete()
|
||||
pivH.wicky_line .delete()
|
||||
pivH.wicky_label.delete()
|
||||
|
||||
pivH := piv.new(sw, bx, opposL, opposB, true, false)
|
||||
|
||||
if dSwingLine
|
||||
pivH.swing_line := line.new (bx , sw , n, sw , color=colBr)
|
||||
if dOpposLine
|
||||
pivH.oppos_line := line.new (opposB, opposL, n, opposL, color=colBr, style=line.style_dotted)
|
||||
if dSFP_Line
|
||||
pivH.wicky_line := line.new (n , high , n, sw , color=colBr2, width=3)
|
||||
if dSFP_Label
|
||||
pivH.wicky_label := label.new(n , high
|
||||
, style=label.style_label_down
|
||||
, text='SFP', textcolor=colBr
|
||||
, color=INV, size=size.normal
|
||||
)
|
||||
|
||||
if pivH.active and not pivH.confirmed
|
||||
|
||||
pivH.swing_line.set_x2(n)
|
||||
pivH.oppos_line.set_x2(n)
|
||||
|
||||
if close < pivH.oppos_prc
|
||||
pivH.confirmed := true
|
||||
|
||||
if pivH.wicky_label.get_x() == n
|
||||
pivH.wicky_label.set_text('SFP\n▼')
|
||||
else
|
||||
label.new(n, high, style=label.style_label_down, text='▼', textcolor=colBr, color=INV, size=size.normal)
|
||||
|
||||
if n - pivH.swing_bix > 500
|
||||
or close > pivH.swing_prc
|
||||
pivH.active := false
|
||||
if not pivH.confirmed
|
||||
pivH.swing_line .delete()
|
||||
pivH.oppos_line .delete()
|
||||
pivH.wicky_line .delete()
|
||||
pivH.wicky_label.delete()
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------}
|
||||
//Bullish Pattern
|
||||
//---------------------------------------------------------------------------------------------------------------------{
|
||||
if bull
|
||||
|
||||
if pl.n()
|
||||
swingL.bix := n-1
|
||||
swingL.prc := pl
|
||||
|
||||
sw = swingL.prc
|
||||
bx = swingL.bix
|
||||
if low < sw
|
||||
and open > sw
|
||||
and close > sw
|
||||
valid = true
|
||||
if validate
|
||||
if ltf_close.size() > 0
|
||||
outsideVolume = 0.
|
||||
totalVolume = ltf_volume.sum()
|
||||
for j = 0 to ltf_close.size() -1
|
||||
if ltf_close.get(j) < sw
|
||||
outsideVolume += ltf_volume.get(j)
|
||||
if (valHigher ? 100 / totalVolume * outsideVolume < percent
|
||||
: 100 / totalVolume * outsideVolume > percent
|
||||
)
|
||||
valid := false
|
||||
if valid
|
||||
|
||||
opposH = sw
|
||||
opposB = n
|
||||
|
||||
for i = 1 to n - bx -1
|
||||
if high[i] > opposH
|
||||
opposH := high[i]
|
||||
opposB := n - i
|
||||
|
||||
if not pivL.confirmed
|
||||
pivL.swing_line .delete()
|
||||
pivL.oppos_line .delete()
|
||||
pivL.wicky_line .delete()
|
||||
pivL.wicky_label.delete()
|
||||
|
||||
pivL := piv.new(sw, bx, opposH, opposB, true, false)
|
||||
|
||||
if dSwingLine
|
||||
pivL.swing_line := line.new (bx , sw , n, sw , color=colBl )
|
||||
if dOpposLine
|
||||
pivL.oppos_line := line.new (opposB, opposH, n, opposH, color=colBl , style=line.style_dotted)
|
||||
if dSFP_Line
|
||||
pivL.wicky_line := line.new (n , low , n, sw , color=colBl2, width=3)
|
||||
if dSFP_Label
|
||||
pivL.wicky_label := label.new(n , low
|
||||
, style=label.style_label_up
|
||||
, text='SFP', textcolor=colBl
|
||||
, color=INV, size=size.normal
|
||||
)
|
||||
|
||||
if pivL.active and not pivL.confirmed
|
||||
|
||||
pivL.swing_line.set_x2(n)
|
||||
pivL.oppos_line.set_x2(n)
|
||||
|
||||
if close > pivL.oppos_prc
|
||||
pivL.confirmed := true
|
||||
|
||||
if pivL.wicky_label.get_x() == n
|
||||
pivL.wicky_label.set_text('▲\nSFP')
|
||||
else
|
||||
label.new(n, low, style=label.style_label_up, text='▲', textcolor=colBl, color=INV, size=size.normal)
|
||||
|
||||
if n - pivL.swing_bix > 500
|
||||
or close < pivL.swing_prc
|
||||
pivL.active := false
|
||||
if not pivL.confirmed
|
||||
pivL.swing_line .delete()
|
||||
pivL.oppos_line .delete()
|
||||
pivL.wicky_line .delete()
|
||||
pivL.wicky_label.delete()
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------}
|
||||
//Dashboard
|
||||
//---------------------------------------------------------------------------------------------------------------------{
|
||||
if barstate.islast and validate and showDash
|
||||
tb.cell(0, 0, str.format("LTF: {0}", res), text_color=color.white, text_size=table_size)
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------}
|
||||
//Alert System
|
||||
//---------------------------------------------------------------------------------------------------------------------{
|
||||
|
||||
// ===== 统一警报系统 =====
|
||||
// 统一警报系统 - 只需添加一次警报即可捕获所有信号
|
||||
|
||||
// 警报频率限制 - 每分钟只触发一次
|
||||
var int last_alert_bearish_sfp = 0
|
||||
var int last_alert_bullish_sfp = 0
|
||||
var int last_alert_bearish_sfp_confirmed = 0
|
||||
var int last_alert_bullish_sfp_confirmed = 0
|
||||
|
||||
// 获取当前时间(分钟级别)
|
||||
current_minute = math.floor(timenow / 60000)
|
||||
|
||||
// 检测所有警报条件并生成对应的JSON消息
|
||||
alert_message = ""
|
||||
|
||||
// 看跌SFP信号检测 - 每分钟限制
|
||||
bearish_sfp_signal = bear and high > swingH.prc and open < swingH.prc and close < swingH.prc and not pivH.confirmed
|
||||
if bearish_sfp_signal and current_minute > last_alert_bearish_sfp
|
||||
alert_message := '{"指标名称":"SwingFailurePattern","交易对":"' + syminfo.ticker + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","摆动高点":"' + str.tostring(swingH.prc, '#.####') + '","事件":"看跌摆动失败模式触发","信号":"bearish_sfp","备注":"突破高点后看跌回落"}'
|
||||
alert(alert_message, alert.freq_once_per_bar_close)
|
||||
last_alert_bearish_sfp := current_minute
|
||||
|
||||
// 在K线上绘制看跌SFP信号标记
|
||||
if showAlerts
|
||||
label.new(bar_index, high + (high - low) * 0.1,
|
||||
text='🔻SFP',
|
||||
style=label.style_label_down,
|
||||
color=color.new(color.red, 20),
|
||||
textcolor=color.white,
|
||||
size=alert_marker_size,
|
||||
tooltip='突破高点后看跌回落\n摆动高点: ' + str.tostring(swingH.prc, '#.####'))
|
||||
|
||||
// 看涨SFP信号检测 - 每分钟限制
|
||||
bullish_sfp_signal = bull and low < swingL.prc and open > swingL.prc and close > swingL.prc and not pivL.confirmed
|
||||
if bullish_sfp_signal and current_minute > last_alert_bullish_sfp
|
||||
alert_message := '{"指标名称":"SwingFailurePattern","交易对":"' + syminfo.ticker + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","摆动低点":"' + str.tostring(swingL.prc, '#.####') + '","事件":"看涨摆动失败模式触发","信号":"bullish_sfp","备注":"跌破低点后看涨反弹"}'
|
||||
alert(alert_message, alert.freq_once_per_bar_close)
|
||||
last_alert_bullish_sfp := current_minute
|
||||
|
||||
// 在K线上绘制看涨SFP信号标记
|
||||
if showAlerts
|
||||
label.new(bar_index, low - (high - low) * 0.1,
|
||||
text='🔺SFP',
|
||||
style=label.style_label_up,
|
||||
color=color.new(color.green, 20),
|
||||
textcolor=color.white,
|
||||
size=alert_marker_size,
|
||||
tooltip='跌破低点后看涨反弹\n摆动低点: ' + str.tostring(swingL.prc, '#.####'))
|
||||
|
||||
// 看跌SFP确认信号 - 每分钟限制
|
||||
bearish_sfp_confirmed = pivH.active and not pivH.confirmed[1] and pivH.confirmed and close < pivH.oppos_prc
|
||||
if bearish_sfp_confirmed and current_minute > last_alert_bearish_sfp_confirmed
|
||||
alert_message := '{"指标名称":"SwingFailurePattern","交易对":"' + syminfo.ticker + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","摆动高点":"' + str.tostring(pivH.swing_prc, '#.####') + '","对立价格":"' + str.tostring(pivH.oppos_prc, '#.####') + '","事件":"看跌摆动失败模式确认","信号":"bearish_sfp_confirmed","备注":"跌破对立低点确认看跌"}'
|
||||
alert(alert_message, alert.freq_once_per_bar_close)
|
||||
last_alert_bearish_sfp_confirmed := current_minute
|
||||
|
||||
// 在K线上绘制看跌SFP确认信号标记
|
||||
if showAlerts
|
||||
label.new(bar_index, high + (high - low) * 0.15,
|
||||
text='✅🔻',
|
||||
style=label.style_label_down,
|
||||
color=color.new(color.maroon, 10),
|
||||
textcolor=color.white,
|
||||
size=alert_marker_size,
|
||||
tooltip='跌破对立低点确认看跌\n摆动高点: ' + str.tostring(pivH.swing_prc, '#.####') + '\n对立价格: ' + str.tostring(pivH.oppos_prc, '#.####'))
|
||||
|
||||
// 看涨SFP确认信号 - 每分钟限制
|
||||
bullish_sfp_confirmed = pivL.active and not pivL.confirmed[1] and pivL.confirmed and close > pivL.oppos_prc
|
||||
if bullish_sfp_confirmed and current_minute > last_alert_bullish_sfp_confirmed
|
||||
alert_message := '{"指标名称":"SwingFailurePattern","交易对":"' + syminfo.ticker + '","触发时间":"' + str.tostring(timenow) + '","时间":"' + str.tostring(time) + '","开盘价":"' + str.tostring(open, '#.####') + '","收盘价":"' + str.tostring(close, '#.####') + '","最高价":"' + str.tostring(high, '#.####') + '","最低价":"' + str.tostring(low, '#.####') + '","摆动低点":"' + str.tostring(pivL.swing_prc, '#.####') + '","对立价格":"' + str.tostring(pivL.oppos_prc, '#.####') + '","事件":"看涨摆动失败模式确认","信号":"bullish_sfp_confirmed","备注":"突破对立高点确认看涨"}'
|
||||
alert(alert_message, alert.freq_once_per_bar_close)
|
||||
last_alert_bullish_sfp_confirmed := current_minute
|
||||
|
||||
// 在K线上绘制看涨SFP确认信号标记
|
||||
if showAlerts
|
||||
label.new(bar_index, low - (high - low) * 0.15,
|
||||
text='✅🔺',
|
||||
style=label.style_label_up,
|
||||
color=color.new(color.teal, 10),
|
||||
textcolor=color.white,
|
||||
size=alert_marker_size,
|
||||
tooltip='突破对立高点确认看涨\n摆动低点: ' + str.tostring(pivL.swing_prc, '#.####') + '\n对立价格: ' + str.tostring(pivL.oppos_prc, '#.####'))
|
||||
|
||||
// ===== 传统警报条件(保留兼容性)=====
|
||||
// 注意:使用统一警报系统时,建议只使用上面的alert()函数
|
||||
// 以下alertcondition保留用于需要单独设置警报的情况
|
||||
|
||||
// 创建用于警报的plot变量
|
||||
plot(swingH.prc, title = '摆动高点', display = display.none)
|
||||
plot(swingL.prc, title = '摆动低点', display = display.none)
|
||||
plot(pivH.oppos_prc, title = '看跌对立价格', display = display.none)
|
||||
plot(pivL.oppos_prc, title = '看涨对立价格', display = display.none)
|
||||
|
||||
// SFP信号警报
|
||||
alertcondition(bearish_sfp_signal, title = '看跌摆动失败模式', message = '{"指标名称":"SwingFailurePattern","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","摆动高点":"{{plot("摆动高点")}}","事件":"看跌摆动失败模式触发","信号":"bearish_sfp","备注":"突破高点后看跌回落"}')
|
||||
|
||||
alertcondition(bullish_sfp_signal, title = '看涨摆动失败模式', message = '{"指标名称":"SwingFailurePattern","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","摆动低点":"{{plot("摆动低点")}}","事件":"看涨摆动失败模式触发","信号":"bullish_sfp","备注":"跌破低点后看涨反弹"}')
|
||||
|
||||
// SFP确认信号警报
|
||||
alertcondition(bearish_sfp_confirmed, title = '看跌摆动失败模式确认', message = '{"指标名称":"SwingFailurePattern","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","摆动高点":"{{plot("摆动高点")}}","对立价格":"{{plot("看跌对立价格")}}","事件":"看跌摆动失败模式确认","信号":"bearish_sfp_confirmed","备注":"跌破对立低点确认看跌"}')
|
||||
|
||||
alertcondition(bullish_sfp_confirmed, title = '看涨摆动失败模式确认', message = '{"指标名称":"SwingFailurePattern","交易对":"{{ticker}}","触发时间":"{{timenow}}","时间":"{{time}}","开盘价":"{{open}}","收盘价":"{{close}}","最高价":"{{high}}","最低价":"{{low}}","摆动低点":"{{plot("摆动低点")}}","对立价格":"{{plot("看涨对立价格")}}","事件":"看涨摆动失败模式确认","信号":"bullish_sfp_confirmed","备注":"突破对立高点确认看涨"}')
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------}
|
||||
Reference in New Issue
Block a user