Session Gap Fill [LuxAlgo]

LuxAlgo · study · 242 行 · 点赞 2,832 · TradingView 原页

本页源码来自 TradingView 公开发布的开源脚本,版权归原作者所有, 请遵循其原始许可(Pine 脚本常见 CC BY-NC-SA / MPL-2.0 / MIT)。 本项目仅用于研究检索与许可范围内的移植。

Pine Script

// 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=6
indicator('Session Gap Fill [LuxAlgo]','LuxAlgo - Session Gap Fill', overlay = true, max_boxes_count = 500, max_labels_count = 500, max_lines_count = 500)
//---------------------------------------------------------------------------------------------------------------------}
//CONSTANTS & STRINGS & INPUTS
//---------------------------------------------------------------------------------------------------------------------{
GREEN                       = #089981
RED                         = #F23645
 
GREEN_80                    = color.new(GREEN,80)
RED_80                      = color.new(RED,80)
RED_50                      = color.new(RED,50)
SILVER_50                   = color.new(color.silver,50)
SILVER_80                   = color.new(color.silver,80)
 
NOOVERLAPPING               = 'No Overlapping Wicks'
OVERLAPPING                 = 'Overlapping'
ALL                         = 'All'
 
TOP_RIGHT                   = 'Top Right'
BOTTOM_RIGHT                = 'Bottom Right'
BOTTOM_LEFT                 = 'Bottom Left'
 
TINY                        = 'Tiny'
SMALL                       = 'Small'
NORMAL                      = 'Normal'
LARGE                       = 'Large'
HUGE                        = 'Huge'
 
DASHBOARD_GROUP             = 'Dashboard'
STYLE_GROUP                 = 'Style'
 
EM_SPACE                    = ' '
FOUR_PER_EM_SPACE           = ' '
HAIR_SPACE                  = ' '
 
filledBullishGapTooltip     = EM_SPACE+HAIR_SPACE+HAIR_SPACE
filledBearishGapTooltip     = FOUR_PER_EM_SPACE+FOUR_PER_EM_SPACE+FOUR_PER_EM_SPACE+HAIR_SPACE
unfilledGapTooltip          = EM_SPACE+EM_SPACE+EM_SPACE+FOUR_PER_EM_SPACE+HAIR_SPACE+HAIR_SPACE
levelTooltip                = EM_SPACE+FOUR_PER_EM_SPACE+HAIR_SPACE+HAIR_SPACE+HAIR_SPACE
 
gapTypeInput                = input.string( ALL,        'Gap Type',             options = [ALL,OVERLAPPING,NOOVERLAPPING])
 
dashboardInput              = input.bool(   true,       'Dashboard',            group=DASHBOARD_GROUP)
dashboardPositionInput      = input.string( TOP_RIGHT,  'Position',             group=DASHBOARD_GROUP, options = [TOP_RIGHT,BOTTOM_RIGHT,BOTTOM_LEFT])
dashboardSizeInput          = input.string( NORMAL,     'Size',                 group=DASHBOARD_GROUP, options = [TINY,SMALL,NORMAL,LARGE,HUGE])
 
filledBullishGapInput       = input.bool(   true,       'Filled Bullish Gap',   group = STYLE_GROUP, inline = 'style1')
filledBullishGapColorInput  = input.color(  GREEN_80,   filledBullishGapTooltip,group = STYLE_GROUP, inline = 'style1')
filledBearishGapInput       = input.bool(   true,       'Filled Bearish Gap',   group = STYLE_GROUP, inline = 'style2')
filledBearishGapColorInput  = input.color(  RED_80,     filledBearishGapTooltip,group = STYLE_GROUP, inline = 'style2')
unfilledGapInput            = input.bool(   true,       'Unfilled Gap',         group = STYLE_GROUP, inline = 'style3')
unfilledGapColorInput       = input.color(  SILVER_80,  unfilledGapTooltip,     group = STYLE_GROUP, inline = 'style3')
divergingInput              = input.bool(   true,       'Max Deviation Level',  group = STYLE_GROUP, inline = 'style4')
divergingColorInput         = input.color(  RED_50,     '',                     group = STYLE_GROUP, inline = 'style4')
levelInput                  = input.bool(   true,       'Open Price Level',     group = STYLE_GROUP, inline = 'style5')
levelColorInput             = input.color(  SILVER_50,  levelTooltip,           group = STYLE_GROUP, inline = 'style5')
 
//---------------------------------------------------------------------------------------------------------------------}
//DATA STRUCTURES & VARIABLES
//---------------------------------------------------------------------------------------------------------------------{
type gap
    int startBar
    int fillBar
    int startTime
    int endTime    
    string gapType
    float openPrice
    float top
    float bottom
    float lastClose    
    box gapArea    
    line extremePrice
    label tag    
    bool filled = false
    bool valid  = false
 
var array<gap> gaps                         = array.new<gap>()
var array<int> filledBullishGaps            = array.new<int>()
var array<int> filledBearishGaps            = array.new<int>()
var array<int> filledBullishReversedGaps    = array.new<int>()
var array<int> filledBearishReversedGaps    = array.new<int>()
var array<int> filledBullishBars            = array.new<int>()
var array<int> filledBearishBars            = array.new<int>()
 
bool gapStart                               = session.isfirstbar_regular
 
var parsedDashboardPosition = switch dashboardPositionInput
    TOP_RIGHT       => position.top_right
    BOTTOM_RIGHT    => position.bottom_right
    BOTTOM_LEFT     => position.bottom_left
 
var parsedDashboardSize = switch dashboardSizeInput
    TINY            => size.tiny
    SMALL           => size.small
    NORMAL          => size.normal
    LARGE           => size.large
    HUGE            => size.huge
 
//---------------------------------------------------------------------------------------------------------------------}
//USER-DEFINED FUNCTIONS
//---------------------------------------------------------------------------------------------------------------------{
gapType() =>    
    bullishGap              = open  > close[1]
    bearishGap              = open  < close[1]
    bullishOverlapping      = low   < high[1]
    bullishNonOverlapping   = low   > high[1]
    bearishOverlapping      = high  > low[1]
    bearishNonOverlapping   = high  < low[1]
 
    overlappingGap          = (bullishGap and bullishOverlapping) or (bearishGap and bearishOverlapping)
    noOverlappingGap        = (bullishGap and bullishNonOverlapping) or (bearishGap and bearishNonOverlapping)
    
    switch
        overlappingGap      => OVERLAPPING
        noOverlappingGap    => NOOVERLAPPING        
        => ''
 
validateGap(gap currentGap) => 
    bool isValid        = currentGap.gapType != '' and (gapTypeInput == ALL or currentGap.gapType == gapTypeInput)
    currentGap.valid    := isValid
 
checkGapType() => 
    bool passedCheck = true
    if gaps.last().gapType == '' or (gapTypeInput != ALL and gaps.last().gapType != gapTypeInput)
        gaps.pop()
        passedCheck := false
    passedCheck
 
gatherStatistics() =>
    if gaps.size() > 0 and checkGapType()
        if gaps.last().openPrice > gaps.last().lastClose
            filledBullishGaps.push(gaps.last().filled ? 1 : 0)
            if gaps.last().filled
                filledBullishReversedGaps.push(close[1] > gaps.last().openPrice ? 1 : 0)
                filledBullishBars.push(gaps.last().fillBar - gaps.last().startBar)
        else
            filledBearishGaps.push(gaps.last().filled ? 1 : 0)
            if gaps.last().filled
                filledBearishReversedGaps.push(close[1] < gaps.last().openPrice ? 1 : 0)
                filledBearishBars.push(gaps.last().fillBar - gaps.last().startBar)
 
gatherData() =>
    if gapStart        
        gatherStatistics()        
        gaps.push(gap.new(bar_index,bar_index,time,time,gapType(),open,high,low,close[1],na,na,na))        
        validateGap(gaps.last())
                    
    if gaps.size() > 0
        gap currentGap          = gaps.last()
        currentGap.endTime      := time        
        currentGap.top          := math.max(currentGap.top,high)
        currentGap.bottom       := math.min(currentGap.bottom,low)
 
        if not currentGap.filled
            bool filledGap      = (currentGap.openPrice > currentGap.lastClose and currentGap.bottom <= currentGap.lastClose) or (currentGap.openPrice < currentGap.lastClose and currentGap.top >= currentGap.lastClose)
            currentGap.filled   := filledGap
            currentGap.fillBar  := bar_index            
            
drawGap(gap currentGap) =>        
    bool isGapDisplayable = currentGap.filled ? (currentGap.openPrice > currentGap.lastClose ? filledBullishGapInput : filledBearishGapInput) : unfilledGapInput
 
    if isGapDisplayable
        if currentGap.filled        
            float tagPrice  = currentGap.openPrice > currentGap.lastClose ? currentGap.top : currentGap.bottom        
            int tagTime     = currentGap.startTime + math.round(0.5*(currentGap.endTime - currentGap.startTime))
            string tagStyle = currentGap.openPrice > currentGap.lastClose ? label.style_label_down : label.style_label_up        
 
            currentGap.tag.delete()
            currentGap.tag := label.new(chart.point.new(tagTime,na,tagPrice),'Filled',xloc.bar_time,yloc.price,color(na),tagStyle,currentGap.openPrice > currentGap.lastClose ? color.new(filledBullishGapColorInput,0) : color.new(filledBearishGapColorInput,0),10)
 
        currentGap.gapArea.delete()    
        currentGap.gapArea := box.new(chart.point.new(currentGap.startTime,na,math.max(currentGap.openPrice,currentGap.lastClose)),chart.point.new(currentGap.endTime,na,math.min(currentGap.openPrice,currentGap.lastClose)),border_color = color(na),bgcolor = currentGap.filled ? (currentGap.openPrice > currentGap.lastClose ? filledBullishGapColorInput : filledBearishGapColorInput) : unfilledGapColorInput, xloc = xloc.bar_time)
 
        if divergingInput
            currentGap.extremePrice.delete()
            float extremePrice = currentGap.openPrice > currentGap.lastClose ? currentGap.top : currentGap.bottom
 
            if extremePrice != currentGap.openPrice
                currentGap.extremePrice := line.new(chart.point.new(currentGap.startTime,na,extremePrice),chart.point.new(currentGap.endTime,na,extremePrice),xloc.bar_time, color = divergingColorInput)
    
drawGaps() =>
    for eachGap in gaps.slice(0,gaps.size() - 1)
        drawGap(eachGap)
    
drawLastGap() =>
    gap lastGap = gaps.last()
    if lastGap.valid
        drawGap(lastGap)
 
cell(table t_able, int column, int row, string data, color = color.white, align = text.align_right) => t_able.cell(column,row,data,text_color = color, text_size = parsedDashboardSize, text_halign = align)
 
drawDashboard() =>
    var table t_able = table.new(parsedDashboardPosition,3,5
     , bgcolor      = #1e222d
     , border_color = #373a46
     , border_width = 1
     , frame_color  = #373a46
     , frame_width  = 1)
 
    cell(t_able,1,0,'Bullish',      align = text.align_left)
    cell(t_able,2,0,'Bearish',      align = text.align_left)
 
    cell(t_able,0,1,'Gaps',         align = text.align_center)
    cell(t_able,0,2,'Filled',       align = text.align_center)  
    cell(t_able,0,3,'Reversed',     align = text.align_center)
    cell(t_able,0,4,'Bars Avg.',    align = text.align_center)
    
    cell(t_able,1,1,str.format('{0, number, 0.00%}',filledBullishGaps.size() / (gaps.size() - 1)))
    cell(t_able,1,2,str.format('{0, number, 0.00%}',filledBullishGaps.sum() / filledBullishGaps.size()))
    cell(t_able,1,3,str.format('{0, number, 0.00%}',filledBullishReversedGaps.sum() / filledBullishReversedGaps.size()))
    cell(t_able,1,4,str.format('{0, number, 0.00}',filledBullishBars.avg()))
 
    cell(t_able,2,1,str.format('{0, number, 0.00%}',filledBearishGaps.size() / (gaps.size() - 1)))            
    cell(t_able,2,2,str.format('{0, number, 0.00%}',filledBearishGaps.sum() / filledBearishGaps.size()))
    cell(t_able,2,3,str.format('{0, number, 0.00%}',filledBearishReversedGaps.sum() / filledBearishReversedGaps.size()))
    cell(t_able,2,4,str.format('{0, number, 0.00}',filledBearishBars.avg()))
    
//---------------------------------------------------------------------------------------------------------------------}
//MUTABLE VARIABLES & EXECUTION
//---------------------------------------------------------------------------------------------------------------------{
gatherData()
 
if barstate.islastconfirmedhistory        
    drawGaps()
 
    if dashboardInput
        drawDashboard()
    
if barstate.islast
    drawLastGap()
 
gap currentGap          = gaps.size() > 0 ? gaps.last() : na
bool isGapDisplayable   = currentGap.filled ? (currentGap.openPrice > currentGap.lastClose ? filledBullishGapInput : filledBearishGapInput) : unfilledGapInput
float currentGapOpen    = not na(currentGap) and currentGap.valid ? currentGap.openPrice : na
float openPrice         = levelInput and isGapDisplayable ? (gapStart ? na : currentGapOpen) : na
 
plot(openPrice,'Open Price Level',levelColorInput,style = plot.style_linebr)
 
//---------------------------------------------------------------------------------------------------------------------}

← 返回列表