Estratégia de negociação quantitativa de alta frequência de dupla filtragem

Autora:ChaoZhang, Data: 2023-11-27 16:11:18
Tags:

img

Resumo

A estratégia é chamada de Double Filtering Quant, que adota técnicas de vários prazos para implementar uma estratégia quantitativa de negociação de alta frequência baseada em ideias de dupla filtragem.

Princípio da estratégia

O princípio central da estratégia é o seguinte:

  1. Usar linhas semanais e diárias para julgar a direção da tendência do mercado como a condição de filtro de direção da estratégia.

  2. Construir o canal no nível de 4 horas para determinar pontos de venda e compra e emitir sinais comerciais.

  3. A consistência das direções julgadas por prazos semanais, diários e de 4 horas pode filtrar muitos sinais falsos e melhorar a confiabilidade dos sinais de negociação.

  4. Usar pontos de retracement de Fibonacci para determinar as posições de lucro e stop-loss para obter lucro rápido e parar as perdas.

Especificamente, a estratégia julga primeiro a direção prioritária da tendência nas linhas semanais e diárias. O princípio para julgar a direção prioritária é: se o preço de fechamento da linha K atual estiver no lado com um ângulo de atraso maior na linha do ciclo, ele é determinado como a direção da linha do ciclo. Em seguida, construa o canal A B C D no nível de 4 horas e determine pontos de compra e venda através da direção do canal e pontos de virada para emitir sinais de negociação. Finalmente, a direção prioritária determinada pela linha do ciclo atual deve ser consistente com a direção do sinal de negociação no nível de 4 horas. Isso pode filtrar muitos sinais falsos e melhorar a confiabilidade dos sinais de negociação.

Vantagens da estratégia

As principais vantagens desta estratégia são:

  1. O mecanismo de filtragem dupla de sinais baseado em vários prazos pode filtrar muito ruído e obter oportunidades de negociação altamente fiáveis.

  2. O uso de canais para construir pontos de compra e venda torna os sinais comerciais claros.

  3. Os pontos de retração de Fibonacci são utilizados para definir posições de captação de lucro e de stop-loss para captação rápida de lucro e de stop-loss.

  4. A estratégia tem poucos parâmetros e é fácil de compreender e dominar.

  5. Boa escalabilidade para fácil otimização e melhoria.

Riscos estratégicos

Os principais riscos desta estratégia são:

  1. A monitorização de muitos prazos aumenta a complexidade e a propensão a erros.

  2. Não considera eventos súbitos de condições especiais de mercado, tais como flutuações drásticas do mercado causadas por grandes acontecimentos noticiosos.

  3. Existe a possibilidade de não se obter lucro suficiente ao estabelecer pontos de stop-loss e de obtenção de lucro utilizando o retracement.

  4. As configurações incorretas dos parâmetros podem conduzir a uma troca excessiva ou a ordens em falta.

Contramedidas:

  1. Reforçar o controlo das anomalias e dos principais acontecimentos noticiosos.

  2. Otimizar a lógica de stop-loss e de lucro para garantir que os lucros alcancem um certo nível.

  3. Testes pormenorizados e otimização de parâmetros para reduzir a probabilidade de excesso de negociação e perdas de ordens.

Orientações para a otimização da estratégia

As principais direcções de otimização desta estratégia são:

  1. Aumentar a possibilidade de utilizar modelos de aprendizagem automática para determinar a direção prioritária das tendências e utilizar mais dados para melhorar a precisão do julgamento.

  2. Teste outros indicadores para construir canais e determinar pontos de compra e venda.

  3. Tente maneiras mais avançadas de tirar lucro e parar de perder, como mover o lucro, saltar o lucro, etc.

  4. Derivar parâmetros ideais a partir dos resultados dos backtests para tornar as definições dos parâmetros mais conformes com os princípios de investimento quantitativo.

  5. Aumentar os mecanismos de monitorização e resposta a grandes acontecimentos súbitos.

Conclusão

Em geral, a idéia central desta estratégia é uma estratégia de negociação quantitativa de alta frequência baseada em dupla filtragem para reduzir o ruído. Ele usa julgamento de vários prazos e determinação de canais de pontos de compra e venda para alcançar filtragem de dupla confiabilidade de sinais de negociação. Ao mesmo tempo, a estratégia tem poucos parâmetros e é fácil de dominar; a escalabilidade é boa e fácil de otimizar e melhorar. Em seguida, a otimização será realizada a partir de aspectos como precisão de julgamento, métodos de captação de lucro e stop-loss e otimização de parâmetros para fazer a estratégia funcionar melhor.


/*backtest
start: 2023-11-19 00:00:00
end: 2023-11-26 00:00:00
period: 1m
basePeriod: 1m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

//@version=5
strategy(title='AG328', shorttitle='AG328', overlay=true )

// Настройки для включения/выключения торговли в Лонг и Шорт
longEnabled = input(true, title="Торговля в Лонг")
shortEnabled = input(true, title="Торговля в Шорт")

smaEnabled = input(true, title="Включить SMA89")
tradeInGrey = input(false, title = "Сигнал в серой зоне")

pipsBuyStop = input.int(0, title="Пунктов добавить для Buy ордера", minval=-50, step=1, maxval=50)
pipsSellStop = input.int(0, title="Пунктов добавить для Sell ордера", minval=-50, step=1, maxval=50)

// Const
LicenseID = 6889430941909
contracts = input.float(0.01, title="Контрактов на сделку:", minval=0, step=0.01, maxval=10)

var float sma = na

var float UW = na
var float DW = na
var bool weeklyLongPriority = na
var bool weeklyShortPriority = na

var float UD = na
var float DD = na
var bool dailyLongPriority = na
var bool dailyShortPriority = na

var float UP = na
var float DOWN = na
var bool h4LongPriority = na
var bool h4ShortPriority = na

var bool LongCondition = na
var bool ShortCondition = na

var bool GreenZone = na
var bool GreyZone = na
var bool RedZone = na

var float LongOrder = 0
var float ShortOrder = 0

var float LongTP = 0
var float ShortTP = 0

var float LongTake = 0
var float ShortTake = 0

var float AA = 0
var float BB = 0
var float CC = 0
var float D = 0

var float AAA = 0
var float BBB = 0
var float CCC = 0
var float DDD = 0

var float stopLong = 0
var float stopShort = 0

var string olderTF = ""
var string oldestTF = ""
var string pivotTF = ""

// Создаем входную настройку для ТФ Пивота
maxValuePivotTF = input.int(2, title="ТФ Пивота старше на:", minval=1, step=1, maxval=3)

// Шаг цены инструмента
stepSize = syminfo.mintick
currentTF = timeframe.period   // Получаем текущий ТФ

if currentTF == "1"                    // Определяем 2 более старших ТФ
    olderTF := "5"
    oldestTF := "15"
    pivotTF := (maxValuePivotTF == 1 ? "5" : (maxValuePivotTF == 2 ? "15" : "60"))
if currentTF == "5"
    olderTF := "15"
    oldestTF := "60"
    pivotTF := (maxValuePivotTF == 1 ? "15" : (maxValuePivotTF == 2 ? "60" : "240"))
if currentTF == "15"
    olderTF := "60"
    oldestTF := "240"
    pivotTF := (maxValuePivotTF == 1 ? "60" : (maxValuePivotTF == 2 ? "240" : "D"))
if currentTF == "60"
    olderTF := "240"
    oldestTF := "D"
    pivotTF := (maxValuePivotTF == 1 ? "240" : (maxValuePivotTF == 2 ? "D" : "W"))
if currentTF == "240"
    olderTF := "D"
    oldestTF := "W"
    pivotTF := (maxValuePivotTF == 1 ? "D" : (maxValuePivotTF == 2 ? "W" : "M"))
if currentTF == "D"
    olderTF := "W"
    oldestTF := "M"
    pivotTF := (maxValuePivotTF == 1 ? "W" : (maxValuePivotTF == 2 ? "M" : "3M"))
if currentTF == "W"
    olderTF := "M"
    oldestTF := "3M"
    pivotTF := (maxValuePivotTF == 1 ? "M" : (maxValuePivotTF == 2 ? "3M" : "3M"))
// Рассчитываем бары ТФ+2
weekHigh0 = request.security(syminfo.tickerid, oldestTF, high)
weekHigh1 = request.security(syminfo.tickerid, oldestTF, high[1])
weekHigh2 = request.security(syminfo.tickerid, oldestTF, high[2])
weekHigh3 = request.security(syminfo.tickerid, oldestTF, high[3])
weekHigh4 = request.security(syminfo.tickerid, oldestTF, high[4])

weekLow0 = request.security(syminfo.tickerid, oldestTF, low)
weekLow1 = request.security(syminfo.tickerid, oldestTF, low[1])
weekLow2 = request.security(syminfo.tickerid, oldestTF, low[2])
weekLow3 = request.security(syminfo.tickerid, oldestTF, low[3])
weekLow4 = request.security(syminfo.tickerid, oldestTF, low[4])

// ТФ+2 Фракталы
weekFractal_UP = weekHigh2 > weekHigh1 and weekHigh2 > weekHigh0 and weekHigh2 > weekHigh3 and weekHigh2 > weekHigh4
weekFractal_DOWN = weekLow2 < weekLow1 and weekLow2 < weekLow0 and weekLow2 < weekLow3 and weekLow2 < weekLow4

if weekFractal_UP
    UW := weekHigh2
    UW
if weekFractal_DOWN
    DW := weekLow2
    DW
// Рисуем UW, DW
plot(UW, title = "UW", color=color.green)
plot(DW, title = "DW", color=color.red)

// ТФ+2 priority
if close > UW
    weeklyLongPriority := true
    weeklyLongPriority
else if close < DW
    weeklyLongPriority := false
    weeklyLongPriority
//weeklyColor = weeklyLongPriority ? color.new(color.green, transp=70) : color.new(color.red, transp=70)
//bgcolor(weeklyColor, title = "WeeklyPriority")

//-----------------------------------------------
// Рассчитываем дневные бары

dayHigh0 = request.security(syminfo.tickerid, olderTF, high)
dayHigh1 = request.security(syminfo.tickerid, olderTF, high[1])
dayHigh2 = request.security(syminfo.tickerid, olderTF, high[2])
dayHigh3 = request.security(syminfo.tickerid, olderTF, high[3])
dayHigh4 = request.security(syminfo.tickerid, olderTF, high[4])

dayLow0 = request.security(syminfo.tickerid, olderTF, low)
dayLow1 = request.security(syminfo.tickerid, olderTF, low[1])
dayLow2 = request.security(syminfo.tickerid, olderTF, low[2])
dayLow3 = request.security(syminfo.tickerid, olderTF, low[3])
dayLow4 = request.security(syminfo.tickerid, olderTF, low[4])

// Дневные Фракталы
dayFractal_UP = dayHigh2 > dayHigh1 and dayHigh2 > dayHigh0 and dayHigh2 > dayHigh3 and dayHigh2 > dayHigh4
dayFractal_DOWN = dayLow2 < dayLow1 and dayLow2 < dayLow0 and dayLow2 < dayLow3 and dayLow2 < dayLow4

if dayFractal_UP
    UD := dayHigh2
    UD
if dayFractal_DOWN
    DD := dayLow2
    DD
// Рисуем UD, DD
//plot(UD, title = "UD", color=color.green)
//plot(DD, title = "DD", color=color.red)

// Daily priority
if close > UD
    dailyLongPriority := true
    dailyLongPriority
else if close < DD
    dailyLongPriority := false
    dailyLongPriority
//dailyColor = dailyLongPriority ? color.new(color.green, transp=70) : color.new(color.red, transp=70)
//bgcolor(dailyColor, title = "DailyPriority")

//-----------------------------------------------
// Рассчитываем 4-часовые бары

h4High0 = request.security(syminfo.tickerid, currentTF, high)
h4High1 = request.security(syminfo.tickerid, currentTF, high[1])
h4High2 = request.security(syminfo.tickerid, currentTF, high[2])
h4High3 = request.security(syminfo.tickerid, currentTF, high[3])
h4High4 = request.security(syminfo.tickerid, currentTF, high[4])

h4Low0 = request.security(syminfo.tickerid, currentTF, low)
h4Low1 = request.security(syminfo.tickerid, currentTF, low[1])
h4Low2 = request.security(syminfo.tickerid, currentTF, low[2])
h4Low3 = request.security(syminfo.tickerid, currentTF, low[3])
h4Low4 = request.security(syminfo.tickerid, currentTF, low[4])

// H4 Фракталы
h4Fractal_UP = h4High2 > h4High1 and h4High2 > h4High0 and h4High2 > h4High3 and h4High2 > h4High4
h4Fractal_DOWN = h4Low2 < h4Low1 and h4Low2 < h4Low0 and h4Low2 < h4Low3 and h4Low2 < h4Low4

if h4Fractal_UP
    UP := h4High2
    UP
if h4Fractal_DOWN
    DOWN := h4Low2
    DOWN
// Рисуем UP, DOWN
plot(UP, title='UP', color=color.new(color.green, 0))
plot(DOWN, title='DOWN', color=color.new(color.red, 0))

// SMA89
sma89 = ta.sma(close, 89)
plot(smaEnabled ? sma89 : na, title='sma89', color=color.new(color.white, transp=10))
//smaColor = close > sma89 ? color.new(color.green, transp=70) : color.new(color.red, transp=70)
//bgcolor(smaColor, title = "smaPriority")

// Condition
LongCondition := weeklyLongPriority and dailyLongPriority and (smaEnabled ? close > sma89 : true)
ShortCondition := weeklyLongPriority == false and dailyLongPriority == false and (smaEnabled ? close < sma89 : true)
ConditionColor = LongCondition ? color.new(color.green, transp=85) : ShortCondition ? color.new(color.red, transp=85) : color.new(color.gray, transp=85)
bgcolor(ConditionColor, title='Condition')

// LOGIC LONG

if AA == 0 and h4Fractal_UP
    AA := UP
if (AA[1] != 0 and BB == 0 and h4Fractal_DOWN) or (AA[1] != 0 and BB != 0 and D == 2 and h4Fractal_DOWN)
    BB := DOWN
    D := 1
if BB != 0 and D == 1 and ta.crossunder(low, BB)
    D := 2
if AA != 0 and BB != 0
    if D == 2 and (D[1] == 1 or D[2] == 1 or D[3] == 1) and h4Fractal_UP
        CC := UP
    else if D == 1 and h4Fractal_UP
        CC := UP
if (AA != 0 and high > AA) or (LongOrder != 0 and high > LongOrder + pipsBuyStop * stepSize) or (tradeInGrey ? ShortCondition : not LongCondition)
    AA := 0
    BB := 0
    CC := 0
    D := 0
//
//plot(AA != 0 ? AA : na, title='A', color=color.new(color.white, transp=10), linewidth=2, style=plot.style_linebr)
//plot(BB != 0 ? BB : na, title='B', color=color.new(color.gray, transp=10), linewidth=2, style=plot.style_linebr)
//plot(CC != 0 ? CC : na, title='C', color=color.new(color.blue, transp=10), linewidth=2, style=plot.style_linebr)
//plot(D != 0 ? D : na, title='D', color=color.new(color.green, transp=80), linewidth=2, style=plot.style_linebr)

// LOGIC SHORT
if AAA == 0 and h4Fractal_DOWN
    AAA := DOWN
if (AAA[1] != 0 and BBB == 0 and h4Fractal_UP) or (AAA[1] != 0 and BBB[1] != 0 and DDD == 2 and h4Fractal_UP)
    BBB := UP
    DDD := 1
if BBB != 0 and DDD == 1 and ta.crossover(high, BBB)
    DDD := 2
if AAA != 0 and BBB != 0
    if DDD == 2 and (DDD[1] == 1 or DDD[2] == 1 or DDD[3] == 1) and h4Fractal_DOWN
        CCC := DOWN
    else if DDD == 1 and h4Fractal_DOWN
        CCC := DOWN
if (AAA != 0 and low < AAA) or (ShortOrder != 0 and low < ShortOrder - pipsSellStop * stepSize) or (tradeInGrey ? LongCondition : not ShortCondition)
    AAA := 0
    BBB := 0
    CCC := 0
    DDD := 0
//
//plot(AAA != 0 ? AAA : na, title='ShortA', color=color.new(color.white, transp=10), linewidth=2, style=plot.style_linebr)
//plot(BBB != 0 ? BBB : na, title='ShortB', color=color.new(color.gray, transp=10), linewidth=2, style=plot.style_linebr)
//plot(CCC != 0 ? CCC : na, title='ShortC', color=color.new(color.blue, transp=10), linewidth=2, style=plot.style_linebr)
//plot(DDD != 0 ? DDD : na, title='ShortD', color=color.new(color.green, transp=80), linewidth=2, style=plot.style_linebr)


// LongOrder
if (tradeInGrey ? not ShortCondition : LongCondition) and CC != 0 and D == 2 and strategy.position_size[1] == 0 and longEnabled
    LongOrder := CC
    LongOrder
else if (tradeInGrey ? ShortCondition : not LongCondition) or strategy.position_size[1] > 0 or (LongOrder != 0 and high > LongOrder + pipsBuyStop * stepSize)
    LongOrder := 0
    LongOrder
plot(LongOrder != 0 ? LongOrder : na, title='LongOrder', color=color.new(color.yellow, transp=10), linewidth=2, style=plot.style_linebr)

// ShortOrder
if (tradeInGrey ? not LongCondition : ShortCondition) and CCC != 0 and DDD == 2 and strategy.position_size[1] == 0 and shortEnabled
    ShortOrder := CCC
    ShortOrder
else if (tradeInGrey ? LongCondition : not ShortCondition) or strategy.position_size[1] < 0 or (ShortOrder != 0 and low < ShortOrder - pipsSellStop * stepSize)
    ShortOrder := 0
    ShortOrder
plot(ShortOrder != 0 ? ShortOrder : na, title='ShortOrder', color=color.new(color.orange, transp=10), linewidth=2, style=plot.style_linebr)

// Fibo Pivots
H = request.security(syminfo.tickerid, pivotTF, high[1])
L = request.security(syminfo.tickerid, pivotTF, low[1])
C = request.security(syminfo.tickerid, pivotTF, close[1])

PP = (H + L + C) / 3
R3 = PP + 1.000 * (H - L)
R2 = PP + 0.618 * (H - L)
R1 = PP + 0.382 * (H - L)
S1 = PP - 0.382 * (H - L)
S2 = PP - 0.618 * (H - L)
S3 = PP - 1.000 * (H - L)

//plot(PP)
//plot(R3)
//plot(R2)
//plot(R1)
//plot(S1)
//plot(S2)
//plot(S3)

// Расчет цены Лонг Тейка
if S3 - LongOrder > LongOrder - DOWN
    LongTP := S3
    LongTP
else if S2 - LongOrder > LongOrder - DOWN
    LongTP := S2
    LongTP
else if S1 - LongOrder > LongOrder - DOWN
    LongTP := S1
    LongTP
else if PP - LongOrder > LongOrder - DOWN
    LongTP := PP
    LongTP
else if R1 - LongOrder > LongOrder - DOWN
    LongTP := R1
    LongTP
else if R2 - LongOrder > LongOrder - DOWN
    LongTP := R2
    LongTP
else if R3 - LongOrder > LongOrder - DOWN
    LongTP := R3
    LongTP
else
    LongTP := 0
    LongTP
//
//plot(LongTake)

if strategy.position_size == 0
    if LongTP == 0 and LongOrder != 0
        LongTake := LongOrder + LongOrder - DOWN
        LongTake
    else
        LongTake := LongTP
        LongTake

plot(series=strategy.position_size > 0 ? LongTake : na, title='LongTake', color=color.new(color.rgb(99, 253, 104), transp=0), linewidth=1, style=plot.style_linebr)

// Расчет цены Шорт Тейка
if ShortOrder - R3 > UP - ShortOrder
    ShortTP := R3
    ShortTP
else if ShortOrder - R2 > UP - ShortOrder
    ShortTP := R2
    ShortTP
else if ShortOrder - R1 > UP - ShortOrder
    ShortTP := R1
    ShortTP
else if ShortOrder - PP > UP - ShortOrder
    ShortTP := PP
    ShortTP
else if ShortOrder - S1 > UP - ShortOrder
    ShortTP := S1
    ShortTP
else if ShortOrder - S2 > UP - ShortOrder
    ShortTP := S2
    ShortTP
else if ShortOrder - S3 > UP - ShortOrder
    ShortTP := S3
    ShortTP
else
    ShortTP := 0
    ShortTP
//
//plot(ShortTP)
if strategy.position_size == 0
    if ShortTP == 0 and ShortOrder != 0
        ShortTake := ShortOrder - (UP - ShortOrder)
        ShortTake
    else
        ShortTake := ShortTP
        ShortTake

plot(series=strategy.position_size < 0 ? ShortTake : na, title='ShortTake', color=color.new(color.rgb(99, 253, 104), transp=0), linewidth=1, style=plot.style_linebr)

// StopForLONG and SHORT
stopLong := math.min(DOWN,ta.lowest(low,3)) -   pipsSellStop*stepSize
//plot(stopLong)
stopShort := math.max(UP,ta.highest(high,3)) + pipsBuyStop*stepSize
//plot(stopShort)

// TRADES LONG
if LongOrder > 0  and close < LongOrder and longEnabled and LongCondition
    strategy.entry('Long', strategy.long, stop=LongOrder + pipsBuyStop*stepSize)
if LongOrder == 0 or not LongCondition or not longEnabled
    strategy.cancel('Long')
strategy.exit('CloseLong', from_entry='Long', stop=stopLong, limit=LongTake - pipsSellStop*stepSize)

// // LONG ALERT !!!
// if longEnabled and LongCondition and LongOrder[1] == 0 and LongOrder != 0
//     alert(str.tostring(LicenseID)+',buystop,GBPUSDb,price='          +str.tostring(LongOrder + pipsBuyStop*stepSize)+',risk='+str.tostring(contracts), alert.freq_once_per_bar_close)
// if longEnabled and LongCondition and LongOrder[1] != 0 and LongOrder != 0 and LongOrder != LongOrder[1]
//     alert(str.tostring(LicenseID)+',cancellongbuystop,GBPUSDb,price='+str.tostring(LongOrder + pipsBuyStop*stepSize)+',risk='+str.tostring(contracts), alert.freq_once_per_bar_close)
// if (strategy.position_size > 0 and (LongTake != LongTake[1] or stopLong != stopLong[1])) or (strategy.position_size > 0 and strategy.position_size[1] == 0 )
//     alert(str.tostring(LicenseID)+',newsltplong,GBPUSDb,sl='+str.tostring(stopLong)+',tp='+str.tostring(LongTake - pipsSellStop*stepSize), alert.freq_once_per_bar_close)
// if strategy.position_size == 0 and ((LongCondition[1] and not LongCondition) or not longEnabled) and (LongOrder[1] != 0 and LongOrder == 0)
//     alert(str.tostring(LicenseID)+',cancellong,GBPUSDb', alert.freq_once_per_bar_close)
    
// // TRADES SHORT
// if ShortOrder > 0 and close > ShortOrder and shortEnabled and ShortCondition
//     strategy.entry('Short', strategy.short, stop=ShortOrder - pipsSellStop*stepSize)
// if ShortOrder == 0 or not ShortCondition or not shortEnabled
//     strategy.cancel('Short')
// strategy.exit('CloseShort', from_entry='Short', stop=stopShort, limit=ShortTake + pipsBuyStop*stepSize)

// // SHORT ALERT !!!
// if shortEnabled and ShortCondition and ShortOrder[1] == 0 and ShortOrder != 0
//     alert(str.tostring(LicenseID)+',sellstop,GBPUSDb,price='           +str.tostring(ShortOrder - pipsSellStop*stepSize)+',risk='+str.tostring(contracts), alert.freq_once_per_bar_close)
// if shortEnabled and ShortCondition and ShortOrder[1] != 0 and ShortOrder != 0 and ShortOrder != ShortOrder[1]
//     alert(str.tostring(LicenseID)+',cancelshortsellstop,GBPUSDb,price='+str.tostring(ShortOrder - pipsSellStop*stepSize)+',risk='+str.tostring(contracts), alert.freq_once_per_bar_close)
// if (strategy.position_size < 0 and (ShortTake != ShortTake[1] or stopShort != stopShort[1])) or (strategy.position_size < 0 and strategy.position_size[1] == 0)
//     alert(str.tostring(LicenseID)+',newsltpshort,GBPUSDb,sl='+str.tostring(stopShort)+',tp='+str.tostring(ShortTake + pipsBuyStop*stepSize), alert.freq_once_per_bar_close)
// if strategy.position_size == 0 and ((ShortCondition[1] and not ShortCondition) or not shortEnabled) and (ShortOrder[1] != 0 and ShortOrder == 0)
//     alert(str.tostring(LicenseID)+',cancelshort,GBPUSDb', alert.freq_once_per_bar_close)



Mais.