Manual do HT Code: robôs e indicadores em C# na HTS
Você escreve em C#, a HTS compila e assina, e o robô roda no seu HTS desktop, no backtest ou ao vivo na sua conta. Este é o manual inteiro: do primeiro robô à referência de cada função.

O HT Code é onde a sua estratégia vira robô. Você escreve em C#, uma linguagem de programação de verdade, com tipos, classes, listas, funções e bibliotecas próprias, e a HTS cuida do resto: compila, testa no histórico, desenha no gráfico e opera ao vivo na sua conta, com o mesmo código do começo ao fim. Se você já tem um setup que opera na mão, uma planilha que calcula sinais ou um robô escrito em outra plataforma, este é o lugar de trazê-lo.
Por que trazer seus algoritmos para cá
Uma linguagem de verdade, sem amarras de script
C# é a linguagem do .NET, usada em sistemas de banco, jogos e software de mercado no mundo todo. Você organiza a estratégia em classes e funções, guarda estado em listas e dicionários, reaproveita código em bibliotecas suas e escreve a lógica que quiser, do cruzamento de médias ao modelo estatístico.
O mesmo número que você vê no gráfico
São mais de 50 indicadores prontos (médias, bandas, osciladores, tendência, volume, VWAP, Ichimoku, padrões de candle) com a mesma conta do gráfico da HTS. O RSI do seu robô é o RSI da tela, candle a candle: o que você enxerga é o que o robô decide.
Backtest que respeita o candle por dentro
O backtest roda no seu PC, sobre os candles do ativo, com slippage, corretagem, posição máxima e as regras da automação. Se o robô decide no meio do candle, o motor anda dentro de cada candle pela "lupa" de 1 minuto, na ordem provável de máxima e mínima, e confere stop e alvo ponto a ponto. O otimizador testa faixas de parâmetros e faz walk-forward (otimiza num trecho e confere no seguinte), para separar estratégia boa de estratégia ajustada ao passado.
Do teste para a conta sem reescrever nada
O código que passou no backtest é o mesmo que opera ao vivo, no Simulador ou na sua conta real, pelo HTS desktop. Você escolhe o ativo, o tempo gráfico e as regras da automação, liga, e acompanha cada ordem, o resultado do dia e o diário do robô.
Decida no fechamento ou no negócio
O robô pode decidir no fechamento de cada candle ou a cada negócio da bolsa, assim que a condição bater. Ao vivo, ele lê o book, a agressão de compra e venda e os últimos negócios: dá para escrever estratégia de fluxo, não só de candle.
Vários tempos e ativos na mesma estratégia
Um robô de 5 minutos pode confirmar a tendência no gráfico de 60 minutos e olhar o dólar enquanto opera o índice. Basta declarar a série que ele usa.
Robôs e indicadores, na mesma linguagem
Você programa os dois: robôs que operam sozinhos e indicadores que desenham no gráfico. O indicador aparece em "Meus indicadores", com linhas, histogramas, bandas preenchidas, marcas, candles pintados e tabela, e com os parâmetros editáveis como qualquer estudo. Muitas vezes o caminho é esse: primeiro o indicador mostra o sinal no gráfico, depois o mesmo raciocínio vira robô.
Proteção que trabalha por você
Seu robô opera com uma rede de segurança. Stop, alvo e as regras de risco que você escolhe (horário, meta e limite de perda do dia) são vigiados pela plataforma o tempo todo, mesmo se o código falhar. Você foca na estratégia; a disciplina fica garantida.
Comece por aqui
- No terminal, abra HT Code (menu Automações). O "+" cria um código novo, em branco. A aba Exemplos, ao lado
do Explorador, tem dezenas de robôs e indicadores prontos para ler e copiar.
- Dê um nome, escreva (ou cole) o código e clique em Compilar. Os problemas aparecem sublinhados no texto e na
lista "Problemas".
- Robô (código que manda ordem): Backtest roda no histórico, no seu PC. Indicador (código que só desenha):
Rodar desenha no gráfico ao lado.
- Para operar de verdade: em Meus robôs (menu Automações) crie uma automação (robô, conta, ativo e tempo gráfico),
escolha as regras e ligue. O robô roda no seu HTS desktop; se o desktop fecha, o robô para e a posição fica.
A categoria do código é automática: quem chama Buy, Sell, ClosePosition, StopLoss ou TakeProfit é robô; quem não chama é indicador; um código sem classe que herde de Robot é biblioteca (código compartilhado, que entra em todos os outros).
Nos exemplos deste manual, um trecho só com comandos roda dentro do OnBarClose; um trecho com campos ou override fica dentro da classe do robô. Todos compilam como estão.
Como um robô é feito
Todo robô é uma classe que herda de Robot. Dentro dela há três partes, sempre nesta ordem de leitura:
| Parte | O que é | Exemplo |
|---|---|---|
| Parâmetros | Valores que você ajusta na tela sem mexer no código, e que o otimizador testa. | [Parameter("Período")] public int Periodo = 20; |
| Variáveis | O que o robô guarda entre um candle e outro: indicadores, contadores, o preço de entrada. | private Sma media = null!; |
| Eventos | Os momentos em que o motor chama o seu código: o início, cada candle, cada negócio, o fim. | public override void OnBarClose() { ... } |
Não precisa escrever using: a API do robô (HTS.Robots e HTS.Robots.Indicators) e o básico do C# (System, System.Linq, System.Collections.Generic) já vêm prontos em todo código. O código começa direto na classe.
O esqueleto de um robô
Um robô completo de cruzamento de preço com a média, com stop e alvo, cabe em poucas linhas:
public class MeuRobo : Robot{ [Parameter("Período", Min = 2, Max = 200)] public int Periodo = 20; private Sma media = null!; public override void OnStart() // uma vez, antes do primeiro candle: crie os indicadores aqui { media = new Sma(Periodo); } public override void OnBarClose() // a cada candle FECHADO: é aqui que o robô decide { media.Update(Current); if (!media.IsReady) return; Plot("Média", media.Value); if (Position.IsFlat && Current.Close > media.Value) { Buy(1); StopLoss(150); TakeProfit(300); } else if (Position.IsLong && Current.Close < media.Value) ClosePosition(); } public override void OnStop() { } // uma vez, no fim (ou quando a automação é desligada)}
Linha a linha:
[Parameter("Período")]transformaPeriodonum campo da tela, com mínimo e máximo.private Sma mediaé a variável que guarda a média móvel entre um candle e outro.OnStartcria a média uma vez só;OnBarClosea avança com o candle que fechou (Current).IsReadydiz que a média já tem candles suficientes; antes disso, o robô espera.Plotdesenha a média no gráfico do backtest;Buy(1)compra um contrato a mercado, eStopLoss(150)e
TakeProfit(300) põem stop e alvo a 150 e 300 pontos do preço médio.
Como o robô roda
O motor entrega o histórico ao robô candle a candle, do mais antigo ao mais recente, e chama OnBarClose uma vez para cada candle fechado. Quando o histórico acaba, ao vivo, o robô continua do mesmo jeito: cada candle que fecha é mais uma chamada. Por isso o mesmo código serve para o backtest e para a conta.
Dentro de cada chamada, o robô enxerga o candle que acabou de fechar e todo o passado até ele, nunca o futuro:
| No código | O que é |
|---|---|
Current | O candle que acabou de fechar (abertura, máxima, mínima, fechamento, volume). |
Closes[0], Closes[1] | O fechamento de agora e o do candle anterior (como Close[1] em outras plataformas). |
media.Value, media[1] | O valor do indicador agora e um candle atrás. |
Position | A posição de agora: zerada, comprada ou vendida, com o preço médio. |
Now, Today | O horário do candle (em Brasília) e o dia do pregão. |
Para decidir no meio do candle, implemente também OnTick: ao vivo, ele roda a cada negócio da bolsa; no backtest, em cada ponto da lupa de 1 minuto. A mesma chamada pode mandar várias ordens a mercado (até 20); elas saem em sequência, cada uma conferida pela posição que as anteriores deixam.
O que o motor faz por você
- Stop e alvo de verdade: o motor confere o toque a cada negócio (e, no backtest, em cada ponto de dentro do
candle), mesmo que o seu código não esteja rodando naquele instante.
- Sem mão dobrada: ao vivo, a entrada pedida numa chamada seguinte espera a anterior chegar à posição; sair e
reduzir passam sempre.
- Regras da automação acima do código: horário, leilão, meta e stop do dia, perdas seguidas, número de operações e
posição máxima valem sempre.
- Código isolado: o robô não acessa internet, arquivos nem o relógio do PC. Tudo o que ele sabe vem do mercado e
tudo o que ele pede passa pelo motor, por isso o backtest e a conta se comportam igual.
Fim do pregão. A última barra do dia chega com o mercado fechado, e nada executa nela. A entrada pedida é recusada (AoOrdemRecusada, FORA_DO_HORARIO, "O pregão de 29/10 já fechou..."). A saída fica guardada e vai ao mercado na abertura do pregão seguinte, uma vez só, nunca maior que a posição daquele momento; recusada de novo com o mercado fechado, o motor manda outra vez enquanto houver posição, com a espera crescendo de 5 s a 30 s. O Zerar guardado não fecha uma posição que virou de lado durante a noite. O mesmo vale para o que o robô pedir depois do fechamento e para a zeragem pela regra. O toque do stop ou do alvo com o mercado fechado não sai: a posição dorme com a proteção, e na abertura quem decide é o preço. Se ele continua além do stop ou do alvo, sai por ele; se voltou, não sai e a proteção segue. Um negócio isolado de noite não é toque. Pendente pedida com o pregão fechado é recusada. Ao vivo, a penúltima barra pode fechar já depois do fim do pregão, no primeiro negócio do leilão de fechamento, e segue as mesmas regras; no backtest ela executa normalmente. Se o mercado for dado por fechado e continuar negociando (mais de 10 min depois, com 2 negócios em até 60 s), o motor volta a operar no mesmo dia. O backtest faz igual: a entrada na última barra é recusada e a saída executa na abertura seguinte, com o escorregamento; se a abertura cruzar o stop ou o alvo, sai por ele. Com "Zerar no fim do pregão" ligado, o backtest zera no fechamento dessa barra, como sempre. Não vale no tempo D, cuja barra só fecha com o primeiro negócio do dia seguinte, nem em ativo de 24 h, que não tem fim de pregão. Se o HTS for fechado antes da abertura, a saída guardada não vai: confira a posição. Num HTS desktop anterior ao host de robôs 1.2.0, a última barra só chega com o primeiro negócio do dia seguinte: atualize o HTS.
Posição atrasada. Se a posição demorar mais de 30 s a mostrar uma execução, o stop, o Zerar e a zeragem pela regra não vendem de novo o que já foi vendido: a saída não sai até a posição mostrar, ou por até 2 min, com um aviso no diário. Se a posição atrasar mais que isso (cerca de 2 min e meio no total), a saída pode vender de novo: confira a posição. A entrada em lote e a stop ou limitada do robô que reduz voltam quando a posição mostrar a entrada.
Os eventos do robô
Início do robô
OnStart()Uma vez, antes do primeiro candle. É onde se criam os indicadores.
private Ema rapida = null!;public override void OnStart() { rapida = new Ema(9); }
Fechamento do candle
OnBarClose()A cada candle FECHADO. Obrigatório: é onde o robô decide.
public override void OnBarClose(){ if (Position.IsFlat && Current.IsBullish) Buy(1);}
A cada negócio
OnTick(Tick tick)A cada negócio, para entrar no meio do candle assim que a condição bater. No backtest, o motor anda dentro de cada candle pela "lupa" de 1m (abertura, máxima e mínima na ordem provável, fechamento) e chama aqui em cada ponto; a lupa cobre até 50 mil minutos, e antes disso cada candle vira 4 pontos (o backtest avisa).
public override void OnTick(Tick tick){ if (Position.IsFlat && CurrentDay is Bar dia && tick.Price > dia.High) Buy(1);}
A cada mudança do book
OnBook(Book book)A cada mudança do book. Só ao vivo (não há book histórico no backtest).
public override void OnBook(Book book){ if (book.BestBid is BookLevel compra && book.BestAsk is BookLevel venda && compra.Quantity > 3 * venda.Quantity) Log("comprador pesado no topo do book");}
Fim do robô
OnStop()Uma vez, no fim do backtest ou quando a automação é desligada.
public override void OnStop() { Log($"Fim: {Trades.Count} operações"); }
Estado do pregão
SessionO estado do pregão do ativo: aberto, em leilão ou fechado (no backtest, desconhecido).
if (Session == SessionState.Auction) return; // não decide em leilão
Ordens, posição, stop e alvo
Compra e venda a mercado
Buy(n)Sell(n)Ordem a mercado de n contratos. No backtest executa no fechamento do candle (ou no ponto da lupa, em OnTick) com o slippage configurado; ao vivo, vai para a sua conta.
if (Position.IsFlat && Current.Close > Current.Open) Buy(1);
Zerar a posição
ClosePosition()Zera a posição que existe, a mercado.
if (Now.HHMM >= 1740 && !Position.IsFlat) ClosePosition();
Posição
PositionA posição líquida: quantidade com sinal e preço médio, com IsFlat, IsLong, IsShort, Contracts e OpenProfit(preco, SymbolInfo) (o resultado aberto em reais).
if (Position.IsLong && Position.OpenProfit(Current.Close, SymbolInfo) > 300) ClosePosition();
Stop e alvo em pontos
StopLoss(pontos)TakeProfit(pontos)Stop e alvo a essa distância do preço médio; chamar de novo substitui. Sem posição e sem ordem no candle, são recusados.
if (Position.IsFlat) { Buy(1); StopLoss(150); TakeProfit(300); }
Cancelar stop e alvo
CancelStops()Remove o stop e o alvo do motor.
if (Position.IsFlat) CancelStops();
Dados do ativo
SymbolInfoO ativo do robô: tick, valor do ponto e moeda.
var reaisPorPonto = SymbolInfo.PointValue * Position.Contracts;Log($"{SymbolInfo.Symbol}: tick {SymbolInfo.TickSize}, R$ {reaisPorPonto} por ponto na posição");
Ordens pendentes, stop móvel e eventos da ordem
Compra limitada e venda limitada
BuyLimit(qtd, preco)SellLimit(qtd, preco)Ordem limitada. Aceitam nome (até 40 caracteres) e comentario (até 80). Repetir o nome substitui a pendente anterior; sem nome, o motor dá um (limite-1...). Até 20 pendentes por robô.
if (Position.IsFlat) BuyLimit(1, Current.Low - 50, "pullback");
Stop de compra e stop de venda
BuyStop(qtd, gatilho)SellStop(qtd, gatilho)Ordem stop: vira a mercado quando o preço toca o gatilho.
if (Position.IsFlat && CurrentDay is Bar dia) BuyStop(1, dia.High + 5, "rompe-maxima");
Stop limitado de compra e de venda
BuyStopLimit(qtd, gatilho, limite)SellStopLimit(...)No gatilho, vira limitada no preço limite. Só no Simulador.
if (Position.IsFlat) BuyStopLimit(1, Current.High + 10, Current.High + 20, "stop-limite");
Cancelar e alterar pendentes
Cancel(nome)CancelAll()Modify(nome, preco)Mexem nas pendentes; PendingOrders lista as de agora.
if (PendingOrders.Count > 0 && Now.HHMM >= 1700) CancelAll();if (!Modify("pullback", Current.Low - 30)) Log("não havia pendente com esse nome");
Pendente que só reduz (entrada com alvo)
Buy(1); SellLimit(1, alvo) é entrada com alvo; se a posição zerar, a pendente cai. Pendentes valem no dia: caem na virada, no teto e no encerramento. No backtest são conferidas a partir do candle seguinte (limite sem slippage, stop com slippage, gap a favor ou contra na abertura).
if (Position.IsFlat) { Buy(1); SellLimit(1, Current.Close + 300, "alvo"); }
Saída parcial e virada de mão
ClosePartial(n)Reverse()Zera parte da posição ou vira a mão.
if (Position.Contracts >= 2 && Position.OpenProfit(Current.Close, SymbolInfo) > 200) ClosePartial(1);
Stop e alvo num preço
StopLossAt(preco)TakeProfitAt(preco)Stop e alvo num preço, em vez de distância.
if (Position.IsLong && PreviousDay is Bar ontem) StopLossAt(ontem.Low);
Stop móvel e break-even
TrailingStop(pontos)BreakEven(gatilho, folga)Stop móvel e break-even, cuidados pelo motor (não viram ordem na corretora até tocar).
if (Position.IsFlat) { Buy(1); StopLoss(150); TrailingStop(100); BreakEven(120, 10); }
Ordem executada
OnFill(Fill fill)Uma ordem executou. Dá para pôr stop e alvo ali.
public override void OnFill(Fill fill){ Log($"executou {fill.Side} {fill.Quantity} a {fill.Price:0}"); if (!Position.IsFlat) { StopLoss(150); TakeProfit(300); }}
Ordem recusada ou cancelada
OnOrderRejected(ordem, codigo, mensagem)OnOrderCanceled(ordem, motivo)A ordem foi recusada ou cancelada. Códigos das pendentes: NOME_INVALIDO, PRECO_INVALIDO, PENDENTES_DEMAIS, STOP_LIMITE_SO_SIMULADOR, SERIE_INDISPONIVEL, SERIE_INVALIDA.
Cada robô envia até 150 ordens por minuto, e cada Modify conta como uma. Acima disso, a entrada e o Modify de uma entrada são recusados com TAXA_EXCEDIDA (a ordem modificada fica como estava). Saídas, cancelamentos e o Modify de um stop ou alvo que só reduz a posição sempre passam.
Na conta real MT5, a saída nunca aumenta a posição na corretora. Se ela tem menos que a carteira do robô, a saída vende só o que há e avisa. Zerada ou do outro lado, a saída é recusada com LIQUIDO_NAO_COBRE: confira a posição. SAIDA_EM_VOO quer dizer que outra saída do mesmo ativo ainda está a caminho. O stop continua valendo e o motor tenta de novo.
public override void OnOrderRejected(PendingOrder order, string code, string message){ Log($"recusada: {code} {message}", LogLevel.Warning);}
Outros tempos, outros ativos e o fluxo
Outro tempo gráfico ou outro ativo
[UsesSeries]CandlesOfDeclare na classe [UsesSeries("15m")] (mesmo ativo, outro tempo) ou [UsesSeries("WDOFUT", "5m")] (outro ativo) e leia com CandlesOf: os candles fechados, o mais antigo primeiro. Tempos: os temporais do gráfico, em minutos (1m a 1439m: 2m, 10m, 45m...), em horas (2h, 3h, 4h...) ou D; "120m" e "2h" são a mesma série. Séries atemporais (Renko, Range...) ainda não. Até 4 séries e 2 ativos extras. No backtest só o mesmo ativo, num tempo múltiplo do teste (num teste atemporal, nenhum), montado como no gráfico: 5m, 15m, 30m e 60m alinhados ao relógio; os outros contando do início do pregão (45m = três de 15m, a partir da abertura). Com o teste num tempo que o banco não guarda (2m, 10m, 45m...), um minuto sem negócio desloca a contagem: a série feita de uma base maior que a do teste (2m pedindo 30m) só sai quando toda barra do teste cabe nos baldes dela; senão fica vazia, com o motivo na recusa.
[UsesSeries("15m")]public class FiltroDe15 : Robot{ public override void OnBarClose() { var c15 = CandlesOf("15m"); if (c15.Count > 0 && c15[^1].IsBullish && Position.IsFlat) Buy(1); }}
Negócios recentes, agressão e ajuste
RecentTicksAggressionSettlementSó ao vivo: os últimos negócios (até 500), a agressão de compra e venda desde que o robô ligou e o ajuste do dia nos futuros.
if (Aggression.Delta > 500 && Position.IsFlat) Buy(1);if (Settlement is double ajuste && Current.Close < ajuste) Log("abaixo do ajuste");
Regras da automação (a tela, não o código)
Na automação a pessoa escolhe: início, não abrir depois de, zerar às, esperar N minutos da abertura, pausar no leilão, meta do dia, stop diário, perdas seguidas, operações por dia e posição máxima. Quem vigia é o motor. Regra nunca bloqueia saída: zerar, reduzir, stop e alvo passam sempre. Encerrado o dia, só saída até o próximo pregão.
Regras escolhidas na tela
RulesAs regras escolhidas na tela, só para ler.
if (Rules.FlattenAt is int zera && Now.HHMM >= zera - 5) return; // perto de zerar, não entra
Situação do dia
StoppedForDayStopReasonEntriesTodayConsecutiveLossesO dia já encerrou, por quê, quantas entradas hoje e quantas perdas seguidas.
if (StoppedForDay) { Log($"parado: {StopReason}"); return; }if (EntriesToday >= 3 || ConsecutiveLosses >= 2) return;
Tempo e calendário da B3
Hora e dia do pregão
NowTodayO robô não lê relógio: Now é o momento do evento em Brasília (no candle, o FIM dele; no negócio, a hora dele) e Today é o pregão. Now.HHMM dá 1740 às 17:40.
if (Now.HHMM < 915 || Now.HHMM >= 1730) return;if (Today.Weekday == Weekday.Friday && Now.Hour >= 16) return;
Gráficos atemporais
SecondsPerCandleCurrent.EndNos gráficos atemporais (Renko, Range, Pontos, Ponto e figura, negócios, volume) a barra não tem duração fixa: SecondsPerCandle é 0. As barras são montadas dos candles de 1 minuto, então a hora tem precisão de minuto: Current.Time é o minuto em que a barra FECHOU (não o começo dela) e Current.End é o fim desse minuto (é ele o Now do fechamento). As que fecham no mesmo minuto ficam 1 segundo uma depois da outra, e a última vai até o fim do minuto. Por isso End - Time não diz quanto a barra levou para se formar; o tempo entre duas barras é a diferença entre os End delas, com precisão de minuto. MinutesSinceOpen conta do minuto em que fechou a primeira barra de hoje. No backtest, a ordem a mercado de uma barra atemporal executa no fechamento do minuto em que ela fechou (o preço de verdade, não o fechamento desenhado do tijolo ou da coluna), e o stop, o alvo e as pendentes são conferidos pelos candles de 1 minuto de dentro dela e pelos que sobram do pregão depois da última barra; o OnTick anda por esses mesmos candles de 1 minuto.
if (SecondsPerCandle == 0 && Candles.Count > 1){ var desdeAAnterior = Current.End - Candles[^2].End; // segundos entre os fechamentos, com precisão de minuto if (desdeAAnterior < 60 && Current.IsBullish) Log("fechou no mesmo minuto da anterior");}
Os gráficos atemporais recomeçam a cada pregão, no 1º negócio do dia: as barras de um dia saem só dos candles de 1 minuto daquele dia. O Renko e o Renko ATR começam na abertura do 1º candle, o ATR recomeça junto, nenhuma barra atravessa a noite e o gap da abertura não vira tijolo. A barra que ainda estava em formação no fim do dia (Pontos, Range, Ponto e figura, negócios, volume) fecha ali, mais curta; o Renko não tem barra em formação. Ao vivo, ela fecha quando o mercado encerra o pregão. É isso que faz o gráfico, o backtest e o robô ao vivo darem as mesmas barras em todo pregão inteiro, com histórico de qualquer tamanho. O 1º pregão de cada histórico baixado fica de fora, porque pode vir cortado; num ativo novo, com um ou dois pregões de histórico, tudo fica. O backtest atemporal cobre os pregões que o histórico de 1 minuto ainda guarda (uma janela que anda: os mais antigos saem), menos esse 1º.
Isso vale para o tempo gráfico do robô. O indicador Renko que você cria no código com new Renko(...) é outro: ele anda nos candles que recebe, sem recomeçar a cada pregão.
Ao vivo, o Now nunca volta: a barra que chega depois de um negócio mais novo (os tijolos que fecharam no mesmo minuto; a última barra do pregão de um tempo como 45m ou 2h, que só fecha com o primeiro candle do pregão seguinte) fica com a hora desse negócio. A barra de um pregão que já passou entra em Candles e chama o OnBarClose (os indicadores andam nela), mas o motor não confere o stop e o alvo pela faixa dela, e as regras ("zerar às", janela) são as da hora de agora.
Ao vivo, num gráfico atemporal, o stop, o alvo, o stop móvel, o break-even e a MEP/MEN são conferidos só pelos negócios: a mínima e a máxima da barra (no Ponto e figura, a coluna inteira; no Renko, o tijolo) têm preços de antes da entrada e não disparam nada. O negócio que chega enquanto a ordem anterior ainda não voltou é conferido assim que ela volta. Se o feed de negócios cair, a proteção espera o próximo negócio.
Ao vivo, num gráfico de tempo (1m, 5m, 60m, D...), o stop, o alvo, o stop móvel, o break-even e a MEP/MEN são conferidos a cada negócio e também pela mínima e pela máxima da barra que fechou. A faixa da barra pega o toque que chegou enquanto a ordem anterior ainda não tinha voltado e o que o feed de negócios perdeu. Ela só vale para a proteção que já existia quando a barra começou. Se a proteção começar ou mudar no meio da barra (a entrada com stop ou alvo, um stop ou um alvo novo, um passo do stop móvel), o fechamento dela confere só os negócios que chegaram depois disso: a mínima e a máxima de antes não disparam nada nem puxam o stop móvel, e o toque na proteção de antes que chegou com a ordem anterior ainda sem voltar também não conta mais. A MEP/MEN de uma entrada sem stop nem alvo segue pela barra inteira. Na barra seguinte, a faixa inteira volta a valer. No backtest é o mesmo: a ordem a mercado executa no fechamento da barra e o stop dela vale a partir da barra seguinte; com OnTick, a partir do ponto seguinte da lupa.
A entrada pedida no OnBarClose da última barra de um pregão que já passou, quando ela só chega no pregão seguinte (mais de 1 h depois do fim dela), é recusada com FORA_DO_HORARIO e o motivo no diário; a saída passa. Não vale para o gráfico D (o D de ontem sempre fecha com o primeiro negócio de hoje: é o sinal para a abertura, como no backtest) nem para a virada da meia-noite de um mercado de 24 h.
Calendário da B3
B3CalendarFeriados, vencimentos e dias úteis da B3.
var du = B3Calendar.BusinessDaysToExpiration(SymbolInfo.Symbol, Today);if (du is <= 1) return; // não opera na véspera do vencimento
Dia, dia anterior, semana e mês
CurrentDayPreviousDayCurrentWeekCurrentMonthAbertura, máxima, mínima, fechamento e volume do período.
if (PreviousDay is Bar ontem && Current.Close > ontem.High && Position.IsFlat) Buy(1);
Minutos desde a abertura
MinutesSinceOpenMinutos desde o primeiro candle do dia.
if (MinutesSinceOpen is < 15) return; // espera 15 minutos de pregão
Séries e números
Candles como séries
ClosesOpensHighsLowsVolumesOs candles como séries: [0] é agora, [1] o candle anterior (como close[1]).
if (Closes[0] > Closes[1] && Closes[1] > Closes[2]) Log("três fechamentos subindo");
Média, soma, máxima e outras contas de série
Valem para qualquer série (candles, indicadores, as suas): Average(n), Sum(n), StdDev(n), Highest(n) e Lowest(n) (valor e há quantos candles), Rising(n), Falling(n), Change(n), Percentile(n, p), Correlation(outra, n).
var maior = Highs.Highest(20);if (Current.Close > maior.Value && Volumes[0] > Volumes.Average(20)) Buy(1);
Série própria
new Series()Uma série sua, um valor por candle (Add).
private readonly Series amplitude = new();public override void OnBarClose(){ amplitude.Add(Current.Range); if (amplitude.Count >= 10 && Current.Range > 2 * amplitude.Average(10)) Log("candle largo");}
Série de sim ou não
BoolSeriesSérie de sim/não: BarsSince() (há quantos candles foi) e ValueWhen(serie).
private readonly BoolSeries subiu = new();public override void OnBarClose(){ subiu.Add(Current.IsBullish); if (subiu.BarsSince() is > 5) Log("6 candles sem alta");}
Valor inválido (NaN)
Na(x)Nz(x, padrao)O aquecimento dos indicadores é NaN: Na diz se não é número e Nz troca por um padrão.
var variacao = Nz(Closes.Change(5), 0);
Cruzamento para cima e para baixo
Crossed.Above(a, b)Crossed.Below(a, b)Cruzamento neste candle, entre duas séries ou entre uma série e um nível.
private Sma curta = null!, longa = null!;public override void OnStart() { curta = new Sma(9); longa = new Sma(21); }public override void OnBarClose(){ curta.Update(Current); longa.Update(Current); if (Crossed.Above(curta, longa) && Position.IsFlat) Buy(1);}
Indicadores
Como usar um indicador
Crie em OnStart e avance em OnBarClose com Update(Current) (o candle) ou Update(valor) (um número). Value é o de agora, Previous o do candle anterior, IsReady diz que saiu do aquecimento. A conta é a mesma do gráfico da HTS. Indicador com várias saídas expõe cada uma (Upper, Lower, Signal...) e o histórico com ...Ago(n). A lista completa, com um exemplo de cada, está na referência no fim deste manual.
private Bollinger bb = null!;public override void OnStart() { bb = new Bollinger(20, 2); }public override void OnBarClose(){ bb.Update(Current.Close); if (!bb.IsReady) return; if (Position.IsFlat && Current.Close < bb.Lower) Buy(1); else if (Position.IsLong && Current.Close > bb.Value) ClosePosition();}
O gráfico
Desenhar uma série
Plot(nome, valor, estilo)Desenha um valor da série nome neste candle: linha, histograma, pontos, área, degrau, cruz ou colunas. Plot(nome, valor, cor) pinta só este ponto (cor por valor).
Plot("Amplitude", Current.Range, PlotStyle.Histogram);Plot("Fechamento", Current.Close, Current.IsBullish ? "#22c55e" : "#ef4444");
Aparência padrão da série
StylePlot(nome, cor, espessura)A aparência padrão da série; a pessoa ainda troca na "Aparência".
StylePlot("Fechamento", "#f59e0b", 2);
Preencher entre duas séries
FillBetween(a, b, cor)Preenche entre duas séries, com cor própria (com transparência, ex.: rgba(...)).
Plot("Máxima", Current.High);Plot("Mínima", Current.Low);FillBetween("Máxima", "Mínima", "rgba(120,120,255,0.1)");
Linha horizontal
HLine(valor, cor, texto)Uma linha horizontal fixa.
HLine(70, "#888888", "sobrecompra");
Pintar o candle e o fundo
PaintCandle(cor)BackgroundColor(cor)Pinta o candle ou o fundo deste candle.
if (Current.Range > 300) PaintCandle("#f59e0b");if (Now.HHMM < 930) BackgroundColor("rgba(255,255,255,0.04)");
Marca no candle
Mark(texto, posicao, forma, cor)Seta, ponto ou texto acima ou abaixo do candle.
if (Current.IsBullish) Mark("C", MarkerPosition.Below, MarkerShape.Arrow, "#22c55e");
Linha e caixa
DrawLineDrawBoxLinha ou caixa entre dois pontos (candles atrás, valor).
if (Candles.Count > 10) DrawLine(10, Candles[^11].Close, 0, Current.Close, "#ffffff");
Tabela no painel
Table(linha, coluna, texto)Uma célula fixa no canto do painel.
Table(0, 0, $"Fechamento {Current.Close:0}");
Indicador sobre o preço
[Overlay]Na classe do indicador, põe as séries sobre o preço; sem ele, o indicador ganha um painel próprio. Cores: "#rrggbb" (ou #rgb, #rrggbbaa, rgba(...)). Limites: 16 séries, 5.000 marcas, 500 desenhos, 50 níveis.
[Overlay]public class MediaNoPreco : Robot{ private Sma media = null!; public override void OnStart() { media = new Sma(20); } public override void OnBarClose() { media.Update(Current); if (media.IsReady) Plot("Média", media.Value); }}
Parâmetros
Parâmetro editável
[Parameter("Nome")]Em um campo público, torna o valor editável na tela (automação, backtest e gráfico). Tipos: int, double, bool, string e qualquer enum seu (vira lista). No atributo: Min, Max, Step, Group, Description, Options (string vira lista) e Format (Time para int HHMM; Color, Symbol, Timeframe para string). Valor fora da faixa é erro na tela, nunca ajuste calado.
[Parameter("Contratos", Min = 1, Max = 10, Group = "Risco")] public int Contratos = 1;[Parameter("Zerar às", Format = ParameterFormat.Time)] public int ZerarAs = 1740;[Parameter("Lado", Options = new[] { "Compra", "Venda" })] public string Lado = "Compra";
Registros e alertas
Registro no diário
Log(mensagem)Vai para o diário do backtest e da automação; com LogLevel muda a cor.
Log($"fechou em {Current.Close:0}");Log("perto do stop diário", LogLevel.Warning);
Alerta
Alert(mensagem)Chama a atenção na hora: toast, bipe e o sino de Avisos no HTS, e uma seta no gráfico quando é indicador.
if (Current.Range > 500) Alert("candle de mais de 500 pontos");
Resultado e operações
Resultado da automação
PnlO resultado da automação: Day (realizado de hoje), Open (aberto), DayWithOpen (o que a meta e o stop diário olham), Total, DayDrawdown e DayRunup. O robô não lê o saldo da conta.
if (Pnl.DayWithOpen <= -500 && !Position.IsFlat) ClosePosition();
Operações fechadas
TradesTradesTodayLastTradeAs operações fechadas, com entrada, saída, contratos, resultado, Points, Mfe e Mae (maior excursão a favor e contra).
if (LastTrade is Trade t && t.Profit < 0) Log($"última perdeu {t.Points:0} pontos");var ganhosHoje = TradesToday.Count(x => x.Profit > 0);
Ganhos e perdas seguidos
ConsecutiveWinsConsecutiveLossesGanhos e perdas seguidos, hoje.
var contratos = ConsecutiveLosses >= 2 ? 1 : 2;if (Position.IsFlat && Current.IsBullish) Buy(contratos);
Bibliotecas
Código compartilhado
Um código sem robô dentro (só classes, structs, enums). Compile-a; a partir daí ela entra em todo robô e indicador seu na próxima compilação deles. Um problema dentro da biblioteca aparece na lista com o nome dela.
public static class Risco{ public static int Contratos(double perdaMaxima, double stopEmPontos, double valorDoPonto) => Math.Max(1, (int)(perdaMaxima / (stopEmPontos * valorDoPonto)));}
O que o código não pode usar
Arquivo, rede, reflexão, threads, processos, relógio (DateTime), aleatório, Console, unsafe, dynamic, extern. O compilador recusa com a linha e explica a troca (DateTime → Now, por exemplo). Cada chamada do robô ao vivo tem um limite de tempo (5 s): um laço infinito para o robô, não a plataforma.
Backtest
Escolha ativo, tempo gráfico e dias; patrimônio, slippage em ticks, corretagem por contrato, posição máxima, zerar no fim do dia e as mesmas regras da automação. O resultado traz métricas (líquido, acerto, payoff, fator de lucro, drawdown máximo), a curva, a lista de trades com MEP/MEN, as execuções, o diário e as recusas do motor. O backtest roda no HTS desktop (precisa do .NET do HTS, instalado uma vez).
Exemplos
O código de cada exemplo está na aba Exemplos do HT Code: abra, leia e use "Copiar código" para levar o código (ou partes dele) para o seu. Todos compilam e rodam como estão.
Primeiros passos
- Cruzamento de médias com stop e alvo — O robô mais simples que vale a pena: compra quando a média curta cruza a longa para cima, vende quando cruza para baixo, sempre com stop e alvo em pontos. Só opera dentro do horário e zera no fim do dia pela regra da automação.
- Uma biblioteca compartilhada e o robô que a usa (dois códigos) — A biblioteca é um código sem robô dentro (vai para "Bibliotecas" no explorador). Compilada, entra em todo robô e indicador seu na próxima compilação deles. Aqui os dois aparecem juntos só para facilitar a leitura; no HT Code a biblioteca é um código e o robô é outro.
- Compra no candle de alta forte, com stop e alvo — O primeiro robô de verdade: quando o candle fecha de alta com corpo grande (força compradora), compra a mercado e já deixa stop e alvo em pontos. Ensina a ler o candle atual (Current), o anterior (CandleAgo) e a conferir se está zerado antes de entrar.
- Janela de horário e número de contratos como parâmetros — Opera só entre o início e o fim escolhidos (horário de Brasília) e zera tudo no "zerar às", sem depender da regra da automação. A entrada é simples (rompe a máxima ou a mínima do candle anterior); o foco é mostrar parâmetros de horário (Format = Time), Now.Between, Now.HHMM e o limite de entradas por dia (EntriesToday).
- Indicador mínimo que plota uma média no gráfico — Um indicador é um código que não manda ordem: só calcula e desenha. Com [Overlay], a linha fica sobre o preço (sem [Overlay], ganha um painel próprio embaixo). Ensina o ciclo básico: criar no OnStart, alimentar com Update no OnBarClose, esperar o aquecimento (IsReady) e plotar com cor e espessura.
- Stop e alvo pelo preço executado, no OnFill, com Log — Em vez de stop e alvo em pontos logo depois do Buy, o robô espera a execução chegar (OnFill) e calcula stop e alvo a partir do PREÇO EXECUTADO (StopLossAt/TakeProfitAt). Ensina a dar nome à ordem, a distinguir a entrada da saída pelo nome e pela origem (Source) e a registrar tudo no Log.
Tendência e médias
- Cruzamento de médias com filtro de ADX — Cruzamento de médias sozinho apanha muito no lateral. Aqui ele só vale quando o ADX mostra tendência (acima do mínimo) e o DI+ ou o DI- confirma o lado. Ensina a combinar dois indicadores: um que dá o sinal e outro que filtra quando o sinal merece confiança.
- SuperTrend seguindo a tendência (sempre posicionado) — O SuperTrend troca de lado quando o preço fecha além da banda de ATR. O robô fica comprado na alta e vendido na baixa, virando a mão (Reverse) na troca. Ensina FlippedNow/IsUptrend, a virada de mão e a usar a própria linha do indicador como stop (StopLossAt), que anda junto a cada candle.
- HiLo Activator com saída parcial — O HiLo compara o fechamento com a média das máximas e das mínimas: fechou acima, tendência de alta; abaixo, de baixa. O robô entra na virada com 2 contratos, realiza metade (ClosePartial) quando anda o alvo parcial e deixa o resto correr até o HiLo virar. Ensina saída em duas etapas e a medir os pontos a favor pelo preço médio.
- SAR parabólico com stop no próprio SAR — Entra na virada do SAR a favor de uma média longa (só compra acima dela, só vende abaixo) e usa o ponto do SAR como stop móvel: a cada candle o stop sobe (ou desce) junto. Ensina a mover o stop por preço com StopLossAt e a filtrar o sinal de virada pelo lado da tendência maior.
- Ichimoku, compra acima da nuvem — Compra quando a Tenkan cruza a Kijun para cima com o preço acima da nuvem (tendência de alta confirmada) e vende no espelho abaixo dela. Sai quando o preço volta para dentro da nuvem. Ensina as linhas do Ichimoku (a nuvem de hoje foi projetada 26 candles atrás), o preenchimento entre duas séries (FillBetween) e a saída por condição.
- Pullback na EMA em tendência, com KAMA contra a lateralidade — Em tendência, o preço costuma voltar à média e seguir. O robô compra quando a mínima toca a EMA e o candle fecha de volta acima dela. A KAMA (média adaptativa, quase parada no lateral) serve de filtro: se ela andou pouco nos últimos candles, o mercado está de lado e o robô não entra. Ensina filtro de lateralidade pela inclinação de uma média.
Rompimentos e canais
- Rompimento da máxima da abertura, com horário e calendário — Espera os primeiros minutos do pregão, marca a máxima e a mínima desse trecho e compra o rompimento. Mostra o uso de Now/Today, MinutesSinceOpen, B3Calendar (não opera na véspera de vencimento) e as séries dos candles.
- Canal de Donchian 20 (a regra das tartarugas) — Compra quando o fechamento passa da máxima dos últimos 20 candles e vende quando perde a mínima. A saída é pelo canal curto do lado oposto (10 candles): sem alvo fixo, deixa a tendência correr. Ensina a comparar com o canal do candle ANTERIOR (UpperAgo/LowerAgo), senão o candle de agora nunca rompe a própria máxima.
- Bollinger squeeze e rompimento — Volatilidade baixa costuma anteceder movimento forte. O robô guarda a largura das bandas numa série própria (Series) e marca "aperto" quando ela é a menor dos últimos N candles. Depois de um aperto, compra o fechamento acima da banda superior (ou vende abaixo da inferior). Ensina a criar uma série sua e a usar Lowest/BarsSince sobre ela.
- Rompimento da máxima e da mínima do dia anterior — A máxima e a mínima de ontem são níveis que todo mundo olha. O robô compra o primeiro fechamento acima da máxima de ontem e vende o primeiro abaixo da mínima, no máximo uma vez por lado no dia. Ensina PreviousDay (o candle diário de ontem montado a partir do histórico), o controle "uma vez por dia" com Today e HLine para marcar os níveis.
- Opening range com BuyStop e SellStop pendentes — Marca a máxima e a mínima dos primeiros minutos do pregão e, ao fim desse trecho, deixa uma compra stop acima e uma venda stop abaixo, uma única vez no dia. A que executar cancela a outra e ganha stop no lado oposto da faixa. Pendente que não executou até o meio-dia é cancelada. Ensina ordens pendentes com nome, OnFill e Cancel por horário.
- Rompimento do canal de Keltner com stop pelo ATR — Compra o fechamento acima da banda superior do Keltner e vende abaixo da inferior. Stop e alvo não são fixos: valem um múltiplo do ATR do momento, arredondado ao tick de 5 pontos do WIN. Em dia agitado o stop abre, em dia calmo fecha. Ensina risco proporcional à volatilidade e a limitar o stop entre um mínimo e um máximo.
Reversão e osciladores
- IFR com as regras da automação, resultado do dia e alerta — Compra IFR sobrevendido e vende sobrecomprado. Lê as regras da automação (não entra perto do "zerar às"), o resultado do dia (para de abrir depois de 2 perdas seguidas por conta própria) e avisa com Alert quando entra.
- Bollinger, volta para a média — Quando o candle fecha fora da banda e o seguinte fecha de volta para dentro, o robô aposta na volta à média: o alvo não é fixo, é a linha do meio da banda, que anda a cada candle. Ensina a ler as bandas do candle anterior (LowerAgo, UpperAgo) e a sair por condição, deixando o stop em pontos só como proteção.
- Estocástico cruzando em zona extrema — Compra quando a linha %K cruza a %D para cima com as duas abaixo de 20 e vende no espelho, acima de 80. Ensina a cruzar duas linhas do MESMO indicador (K e D, com o valor do candle anterior em [1] e DAgo(1)) e a exigir que o cruzamento aconteça dentro da zona: cruzar no meio do caminho não vale.
- Williams %R a favor da tendência — Reversão curta dentro da tendência maior: com o preço acima da média de 50, compra quando o %R sai de baixo de −80 (correção acabando); abaixo da média, vende quando sai de cima de −20. Ensina a combinar um oscilador (que vai de −100 a 0) com um filtro de tendência e a proteger o lucro com BreakEven (stop vai para a entrada depois de andar a favor).
- CCI voltando de −100 e de +100 — Compra quando o CCI volta para cima de −100 e vende quando volta para baixo de +100; a saída é o CCI cruzar o zero (a "volta" terminou), com stop em pontos por segurança. Ensina a sair pelo próprio indicador e a limitar o número de entradas por dia (EntriesToday), coisa que todo robô de reversão precisa em dia de tendência forte.
- Divergência de IFR no fundo — O preço faz um fundo mais baixo que o anterior, mas o IFR faz um fundo mais alto: a venda está perdendo força. O robô acha os fundos com Swings (um fundo só é confirmado alguns candles depois, quando o preço já subiu dos dois lados) e lê o IFR no candle do fundo com ifr[atraso]. Ensina a guardar o "fundo anterior" e comparar dois pontos no tempo.
Fluxo: negócio, agressão e book
- Ao vivo, por negócio e book (só no HTS desktop) — OnBook só chama ao vivo; OnTick chama ao vivo e, no backtest, em cada ponto da lupa de 1m (negócio sintético, sem agressor: aqui o robô não entra no backtest). Compra quando o book mostra mais compra do que venda nos 3 primeiros níveis e o último negócio foi agressão de compra; sai no stop/alvo do motor. A entrada da chamada seguinte espera a anterior chegar à posição: o motor garante.
- Saldo de agressão do candle como gatilho (só ao vivo) — Aggression soma a agressão desde que o robô ligou; guardando o saldo no começo de cada candle, a diferença no fechamento é o saldo DAQUELE candle. Compra quando o candle fecha de alta com saldo de compra acima do mínimo e vende no espelho. No backtest a agressão é sempre zero: o robô roda, mas não entra (o candle não diz quem agrediu).
- Desequilíbrio do book, com spread fechado (só ao vivo) — Lê o book em OnBook de dois jeitos: só o melhor nível (BestBid × BestAsk) e a soma dos 3 primeiros. Entra no OnTick quando os dois apontam o mesmo lado e o spread está fechado: spread aberto (mais que N ticks) é mercado sem liquidez, e aí não entra. No backtest não existe book: o robô roda sem entrar.
- Lotes grandes em sequência (só ao vivo) — Conta negócios grandes (lote acima de N) agredindo o mesmo lado, um atrás do outro, dentro de poucos segundos: é o "player" entrando. Um lote grande do lado contrário zera a contagem. Ensina a guardar estado entre chamadas do OnTick e a usar o horário do negócio (TimeMs). No backtest a quantidade vem 0 e o agressor desconhecido: nunca conta.
- VWAP do dia com confirmação da agressão — Compra quando o preço volta para cima da VWAP do dia e vende quando perde a VWAP; ao vivo, só entra se o saldo de agressão do candle confirmar o lado. Sem agressão (backtest), cai para a confirmação pelo próprio candle. Ensina a escrever um robô que funciona nos dois mundos: o fluxo melhora o sinal quando existe, e o sinal não depende dele.
- Tape reading pela velocidade dos negócios (só ao vivo) — Conta em RecentTicks quantos negócios saíram no último minuto e para onde o preço foi nesse minuto. Mercado acelerando (muito mais negócios que o normal) e andando para um lado: entra a favor. Ensina a percorrer RecentTicks do mais novo para o mais antigo e a parar no corte de tempo. No backtest RecentTicks vem vazio: o robô roda sem entrar.
- Absorção: muita agressão e o preço não anda (só ao vivo) — Se o vendedor agride forte num candle e mesmo assim o preço não cai (candle pequeno, fechando no terço de cima), tem alguém grande comprando no limite: a venda foi absorvida. O robô compra (e vende no espelho). Ensina a cruzar o fluxo com a forma do candle e a comparar com a amplitude média. No backtest não há agressão: o robô roda sem entrar.
Quant e estatística
- Z-score do preço (reversão à média) — O z-score mede quantos desvios-padrão o fechamento está longe da média: z = (preço − média) / desvio. Abaixo de −2 o preço está "esticado" para baixo; o robô compra quando o z volta a subir e sai quando chega a zero (a média). Ensina Closes.Average e Closes.StdDev e a guardar o próprio indicador numa Series para comparar com o candle anterior.
- Regime de volatilidade (só opera no meio da distribuição) — Guarda o ATR de cada candle numa Series e calcula, sobre os últimos 200, os percentis 30 e 80. Mercado parado demais (abaixo do 30) não paga o stop; nervoso demais (acima do 80) violina. Fora dessa faixa o cruzamento de médias é ignorado. Ensina Percentile como filtro de regime, que serve para qualquer estratégia.
- Momentum de séries temporais — Fica do lado do retorno dos últimos N candles: retorno positivo, comprado; negativo, vendido. Para não virar a mão a cada ruído, o retorno é dividido pela volatilidade (HistoricalVolatility) e só conta quando passa de um limiar. Ensina PercentChange, HistoricalVolatility e Reverse (vira a posição numa ordem só).
- Regressão linear com R² como filtro — Ajusta uma reta aos últimos N fechamentos. A inclinação (Slope) diz a direção, em pontos por candle; o R² (0 a 1) diz quanto a reta explica o preço: perto de 1 é tendência limpa, perto de 0 é bagunça. Só opera com R² alto, comprando o recuo até a reta na alta e vendendo o repique na baixa. Ensina LinearRegression, Slope, R2 e Forecast.
- Correlação WIN × WDO — Índice e dólar costumam andar em sentidos opostos. O robô lê o WDO de 5m com [UsesSeries], calcula a correlação dos retornos dos dois e, com correlação bem negativa, só compra WIN se o dólar caiu no candle (e vende se subiu). No backtest a tela manda o WDO pronto (as barras do gráfico); sem candles do dólar (sem histórico no período, ou no começo do pregão), o robô avisa uma vez e opera sem o filtro. Ensina Correlation e Series.
- Rompimento por percentil 95 da amplitude — Um candle "fora da curva" é o que tem amplitude maior que 95% dos últimos 200. Quando ele aparece fechando perto da ponta (máxima na alta, mínima na baixa), o robô entra a favor. Ensina a calcular o percentil ANTES de incluir o candle atual (senão ele se compara consigo mesmo) e a usar a própria amplitude como medida do stop.
- Quantidade de contratos pela volatilidade — O risco em reais por operação é fixo; o que muda é o tamanho. Contratos = risco ÷ (stop em pontos × valor do ponto), com o stop em múltiplos do ATR: mercado calmo, stop curto e mais contratos; nervoso, stop longo e menos contratos. Ensina SymbolInfo.PointValue (WIN: R$ 0,20 por ponto), arredondamento e Shifted (máxima dos candles ANTERIORES).
Rastreadores de preço e alertas
- Aviso de nova máxima e nova mínima do dia — Indicador que vigia o pregão: desenha a máxima e a mínima do dia em degrau e, quando um candle fecha renovando uma delas, marca o candle e avisa com Alert. Só avisa a máxima que ficou de pé por alguns candles (em tendência, não avisa a cada candle). Ensina a guardar estado por dia (zerando na virada), CurrentDay e contadores entre candles.
- Preço tocando os pivôs do dia anterior — Calcula os pivôs clássicos com a máxima, a mínima e o fechamento de ontem (PreviousDay + Pivots.Classic) e marca o candle que encosta em um deles, com uma tolerância em pontos. Cada nível só avisa uma vez por dia. Ensina a ler o dia anterior agregado e a evitar avisos repetidos guardando o que já tocou.
- Gap de abertura contra o fechamento de ontem — No primeiro candle do dia compara a abertura com o fechamento do dia anterior. Gap maior que o mínimo vira marca, alerta e uma caixa (DrawBox) do tamanho do gap; depois acompanha se o gap foi fechado no mesmo dia. Ensina IsFirstCandleOfDay, PreviousDay e desenho entre dois pontos.
- Candle de volume anormal — Painel próprio com o volume em colunas e a linha de corte (média + N desvios-padrão dos últimos candles). O candle cujo volume passa do corte é pintado no gráfico de preço e ganha uma marca. Ensina a ler a série Volumes por posição (Volumes[1] = candle anterior), cor por valor e o cuidado de comparar com a janela ANTERIOR ao candle.
- Distância do VWAP em desvios — Painel próprio que mostra quantos desvios-padrão o fechamento está longe do VWAP do dia (um "z-score" do VWAP). Pinta o fundo quando passa de ±2 e avisa quando o preço volta de lá. Ensina Vwap (zera sozinho a cada pregão), StdDev alimentado com a diferença preço − VWAP e HLine para as faixas de referência.
- Padrões de candle marcados no gráfico — Procura martelo, estrela cadente, engolfo de alta e engolfo de baixa (Patterns, com a mesma régua do catálogo do gráfico) e marca cada um com texto e cor. Um filtro opcional só mostra o padrão a favor da média longa. Ensina a chamar Patterns com o índice do candle atual e a montar a lista de achados para uma marca só.
- Painel com o resumo do dia — Uma tabela (Table) no canto do gráfico com abertura, máxima, mínima, amplitude, variação contra o fechamento de ontem, volume e a posição do preço dentro da faixa do dia. Ensina CurrentDay e PreviousDay (agregados prontos), a grade de linhas e colunas da Table e a formatação dos números.
Gestão de risco e ordens
- Rompimento com ordens pendentes, alvo limitado e stop móvel — Ordens completas: em vez de comprar a mercado no fechamento, o robô deixa uma COMPRA STOP acima do canal e uma VENDA STOP abaixo dele. O nome é único: colocar de novo "rompe-cima" no candle seguinte SUBSTITUI a anterior (o canal anda). Quando uma executa (OnFill), cancela a outra, põe o alvo como ordem LIMITADA (só reduz a posição) e liga o stop móvel e o break-even. Pendente vale no dia: o motor cancela na virada (e avisa em OnOrderCanceled).
- Saída parcial no primeiro alvo e stop no preço de entrada — Entra com vários contratos no cruzamento de médias. Quando a posição anda o primeiro alvo a favor, realiza metade com ClosePartial e leva o stop do resto para o preço médio (StopLossAt): daí em diante a operação não perde. O resto sai no alvo final ou no stop. Ensina Position.OpenPoints, Position.Contracts e a ordem das chamadas numa decisão.
- Stop móvel pela volatilidade (ATR) — Em vez de um stop fixo em pontos, o stop fica a N vezes o ATR do preço e só anda a favor: a cada candle o robô calcula o stop novo e, se for melhor que o atual, move com StopLossAt. Mercado calmo, stop curto; mercado nervoso, stop largo. O stop aparece no gráfico como pontos. Ensina Atr, StopLossAt e o arredondamento ao tick do ativo.
- Stop diário e meta do próprio robô — Além das regras da automação, o robô vigia o resultado do dia em reais (Pnl.DayWithOpen: o realizado mais o aberto). Bateu a perda máxima ou a meta, zera, cancela as pendentes e encerra o dia por conta própria: só volta a operar no pregão seguinte. Ensina Pnl, TradesToday, guardar o dia encerrado e mostrar o placar numa Table.
- Quantidade de contratos pelo risco em reais — O tamanho da mão sai da conta: perda máxima por operação ÷ (stop em pontos × valor do ponto do ativo). Stop curto permite mais contratos, stop longo menos, e a perda em reais fica a mesma. O stop é a mínima do candle de sinal (ou a máxima, na venda). Ensina SymbolInfo.PointValue, o arredondamento para baixo e o limite de contratos.
- Compra limitada que acompanha o preço (Modify) e trata recusa e cancelamento — Em tendência de alta (preço acima da média), deixa uma COMPRA LIMITADA um pouco abaixo da mínima do último candle e, a cada candle, sobe a ordem com Modify em vez de cancelar e mandar outra. A tendência virou: cancela. Executou: stop e alvo. OnOrderCanceled e OnOrderRejected contam o que aconteceu; três recusas no dia param a pendente.
Indicadores no gráfico
- Indicador no gráfico com bandas, preenchimento e cor por valor — Sem automação (não manda ordem): vira estudo em "Meus indicadores". Mostra StylePlot, FillBetween, cor por valor, PaintCandle, BackgroundColor e a tabela (Table) no canto do painel.
- Heikin-Ashi pintando os candles do gráfico — Calcula os candles Heikin-Ashi (médias que suavizam o ruído) e pinta cada candle normal com a cor do Heikin-Ashi: verde em sequência de alta, vermelho em sequência de baixa, e uma cor mais fraca quando o Heikin-Ashi tem sombra contra a tendência (perda de força). Marca a virada de cor. Ensina HeikinAshi, CandleAgo e PaintCandle.
- Renko sobre o gráfico, com marcas de virada — Monta tijolos Renko de tamanho fixo em pontos sobre o fechamento dos candles e desenha o nível do último tijolo em degrau, com a cor do lado. Quando o Renko vira de lado, marca o candle e conta a sequência de tijolos. Ensina Renko (Bricks, NewBricks, FlippedNow, Direction) e a diferença entre o tempo do candle e o "tempo" do tijolo.
- MACD em painel próprio com histograma de quatro cores — Sem [Overlay], o indicador ganha um painel com escala própria. Plota a linha do MACD, a linha de sinal e o histograma colorido pelo sinal E pela força: verde forte subindo, verde fraco caindo, vermelho forte descendo, vermelho fraco voltando. Ensina Macd (Line, Signal, Histogram, HistogramAgo) e o estilo definido pelo primeiro Plot.
- Pivôs do dia (clássico, Fibonacci ou Camarilla) com zona e tabela — Calcula os pivôs com o dia anterior e desenha os sete níveis em degrau (cada dia com os seus), preenche a zona entre S1 e R1 e mostra os valores de hoje numa Table. Ensina a escolher o cálculo por parâmetro (enum), Pivots, FillBetween entre duas séries e por que níveis que mudam por dia vão em Plot (degrau), e não em HLine.
- Canal de regressão linear com preenchimento — Ajusta uma reta aos últimos N fechamentos (mínimos quadrados) e desenha a linha central e as bandas a N erros-padrão, com a área entre elas preenchida. A cor da linha central segue a inclinação, e o candle que fecha fora do canal é pintado. Ensina RegressionChannel (Upper, Lower, Slope), LinearRegression.R2 e FillBetween.
Referência da API
Tudo o que o robô pode usar está aqui; o resto o compilador recusa.
API · Robô e contexto
O robô
RobotA classe-base de todo robô da HTS. Seu robô herda dela, declara os parâmetros com ParameterAttribute e escreve a decisão em OnBarClose (no fechamento de cada candle) e, se quiser entrar no meio do candle assim que a condição bater, em OnTick (a cada negócio). Regras que o motor garante e que o robô não precisa (nem consegue) burlar: uma chamada por evento: candle fechado (OnBarClose) e, se o robô implementar, negócio (OnTick) e book (OnBook). No backtest o OnTick também roda: o motor anda DENTRO de cada candle pelos candles de 1m (abertura, máxima e mínima na ordem provável, fechamento; sem 1m, os 4 pontos do próprio candle) e chama o robô em cada ponto; numa chamada, quantas ordens a mercado o robô quiser (Buy, Sell, ClosePosition, ClosePartial, Reverse), até 20 (a 21ª é recusada: ORDENS_DEMAIS). Elas saem em sequência e cada uma é conferida pela posição que as anteriores deixam: Buy(1); ClosePosition(); compra e zera; entre chamadas, a entrada nova espera a anterior chegar à posição (ao vivo): o robô que compra "enquanto zerado" a cada negócio não dobra a mão. A recusa vem com ORDEM_EM_ANDAMENTO; pendentes (limite, stop, stop-limite): até 20, com nome único, valem no dia; as regras da automação (horário, stop diário, meta, perdas seguidas, operações, posição máxima) são do motor.
public class CompraNoRompimento : Robot{ [Parameter("Stop (pontos)", Min = 50, Max = 1000)] public int Stop = 150; public override void OnBarClose() { // compra quando o candle fecha acima da máxima do anterior if (Position.IsFlat && Current.Close > Highs[1]) { Buy(1); StopLoss(Stop); } }}
| Membro | O que faz |
|---|---|
IContext Context | O contexto da chamada atual. Só existe entre OnStart e OnStop. |
virtual void OnStart() | Uma vez, antes do primeiro candle. Crie aqui os indicadores. |
abstract void OnBarClose() | A cada candle fechado. É aqui que o robô decide. |
virtual void OnTick(Tick tick) | A cada negócio do mercado: para entrar (ou sair) no meio do candle, assim que a condição bater. Manda ordem como o OnBarClose (várias a mercado por chamada, até 20). Ao vivo, é cada negócio da bolsa. No backtest, o motor anda dentro de cada candle pelos candles de 1m e chama aqui em cada ponto: abertura → mínima e máxima na ordem provável (1m de alta: a mínima antes; de baixa: a máxima antes) → fechamento; sem 1m, os 4 pontos do próprio candle. O negócio do backtest é sintético: o preço do ponto, quantidade 0 e agressor desconhecido (Flat); a ordem a mercado executa no preço do ponto com o slippage; stop, alvo e pendentes são conferidos ponto a ponto (a pendente posta num ponto vale a partir do seguinte). Candles e Current continuam no último candle FECHADO (o que está se formando não aparece), como ao vivo. Quem não precisa, não implementa: sem ele, o backtest é só por candle fechado. |
virtual void OnBook(Book book) | A cada mudança do book, SÓ AO VIVO (não há book histórico no backtest). As mesmas regras de OnTick. |
virtual void OnStop() | Uma vez, depois do último candle (ou quando o robô é desligado). |
IReadOnlyList<Candle> Candles | Candles fechados até agora, do mais antigo ao atual. O último é Current. |
Candle Current | O candle que acabou de fechar e motivou a chamada de OnBarClose. Em OnTick, o último candle FECHADO (o que está se formando não aparece, ao vivo e no backtest). |
Position Position | Posição líquida agora, depois das execuções do candle anterior. |
SymbolInfo SymbolInfo | O ativo e o contrato (tick, valor do ponto). |
double DayProfit | Resultado realizado do dia (em dinheiro), já com corretagem no backtest. Ao vivo, o realizado do dia do robô na conta (Simulador ou MT5). |
double Equity | Patrimônio agora: inicial + realizado + aberto ao fechamento do candle atual. |
bool StoppedForDay | O robô encerrou o dia (stop diário, meta, perdas seguidas ou "zerar às"). Enquanto true, entradas são recusadas e o motor zera o que aparecer, até o próximo pregão. Saídas passam sempre. |
Book Book | O book de agora (ao vivo; vazio no backtest). |
Tick? LastTick | O último negócio (ao vivo; no backtest, o ponto sintético do OnTick, ou null sem ele). |
void Buy(int quantity = 1) | Compra a mercado. No backtest executa no fechamento deste candle (em OnBarClose) ou no preço do ponto (em OnTick), mais o slippage configurado. Pode haver outras na mesma chamada (até 20, em sequência). |
void Sell(int quantity = 1) | Vende a mercado. Como Buy, menos o slippage. |
void ClosePosition() | Zera a posição a mercado: a de agora mais as ordens a mercado já pedidas nesta chamada (Buy(1); ClosePosition(); zera a compra). Sem posição, não faz nada. |
void StopLoss(double points) | Stop de perda a points do preço médio da posição (a que existe ou a que esta decisão abrir). Executa como ordem a mercado no candle em que o preço tocar (com OnTick no backtest, no ponto em que tocar, a partir do seguinte), com slippage. Chamar de novo substitui o anterior; CancelStops remove. |
void TakeProfit(double points) | Alvo (realização) a points do preço médio, a favor. Executa no toque, sem slippage. |
void CancelStops() | Remove stop e alvo pendentes. |
void Log(string message) | Registro que aparece no painel do backtest e no diário do robô ao vivo. |
void Log(string message, LogLevel level) | Registro com nível: Log("x", LogLevel.Warning). |
void Alert(string message) | Alerta: aviso na hora no HTS (toast, som, sino) e seta no gráfico. |
void Plot(string name, double value, PlotStyle style = PlotStyle.Line) | Plota um valor da série name neste candle: é o que o gráfico desenha (indicador) e o que o painel do backtest mostra. Uma série, um valor por candle; chamar de novo no mesmo candle substitui. Candle sem chamada fica sem valor (buraco na linha). O estilo vale da primeira chamada da série. Valor não finito = sem valor. |
void Plot(string name, double value, string color) | Plota com a cor deste ponto (cor por valor). |
void StylePlot(string name, string? color, double width = 0) | Cor e espessura padrão da série. |
void FillBetween(string seriesA, string seriesB, string? color = null) | Preenche entre duas séries. |
void HLine(double value, string? color = null, string? text = null) | Linha horizontal no painel. |
void PaintCandle(string color) | Pinta o candle atual. |
void BackgroundColor(string color) | Pinta o fundo da coluna do candle atual. |
void Mark(string text, MarkerPosition position = MarkerPosition.Above, MarkerShape shape = MarkerShape.Arrow, string? color = null) | Marca no candle atual (seta, ponto ou texto; acima da máxima ou abaixo da mínima). |
void Mark(string text, double value, MarkerPosition position = MarkerPosition.Above, MarkerShape shape = MarkerShape.Arrow, string? color = null) | Marca ancorada num valor. |
void DrawLine(int barsAgo1, double value1, int barsAgo2, double value2, string? color = null) | Linha entre dois pontos (candles atrás, valor). |
void DrawBox(int barsAgo1, double value1, int barsAgo2, double value2, string? color = null) | Caixa entre dois cantos (candles atrás, valor). |
void Table(int row, int column, string text) | Célula da tabela no canto do painel. |
Timestamp Now | O momento deste evento em Brasília: no fechamento de candle, o fim do candle (End quando a barra traz); num negócio/book, a hora dele. Ao vivo, nunca volta (o candle que chega depois de um negócio mais novo fica com a hora do negócio). if (Now.HHMM >= 1750) ClosePosition(); |
Date Today | O pregão deste evento (a data do candle que fechou, ou do negócio). |
int SecondsPerCandle | O tempo gráfico em segundos (300 = 5 min); 0 nos gráficos atemporais (Renko, Range, Pontos, Ponto e figura, negócios, volume), em que a barra não tem duração fixa, e quando não se sabe. if (SecondsPerCandle == 0) Log("gráfico atemporal: a barra não tem duração fixa (Current.End é o fim do minuto em que fechou)"); |
bool IsFirstCandleOfDay | O candle atual é o primeiro do dia no histórico. |
Bar? CurrentDay | O dia até agora: abertura do primeiro candle do dia, máxima, mínima, fechamento atual, volume. |
Bar? PreviousDay | O dia anterior inteiro (o que está no histórico); null se não está. |
Bar? CurrentWeek | A semana até agora (de segunda-feira). |
Bar? CurrentMonth | O mês até agora. |
AutomationRules Rules | As regras escolhidas na tela (horário, leilão, meta, stop diário, perdas seguidas, operações, posição máxima). O motor vigia: o robô só lê, por exemplo para não tentar entrar fora da janela. if (Rules.FlattenAt is int z && Now.HHMM >= z - 5) return; // perto de zerar, não entra |
SessionState Session | O estado do pregão (ao vivo): aberto, leilão, fechado; no backtest, desconhecido. |
int? MinutesSinceOpen | Minutos desde o primeiro candle do dia (no atemporal, o minuto em que fechou a primeira barra de hoje); null sem candle hoje. |
int EntriesToday | Entradas que a automação fez hoje. |
int ConsecutiveLosses | Fechamentos seguidos com perda, hoje. |
string? StopReason | Por que a automação encerrou o dia; null se não encerrou. |
Pnl Pnl | O resultado da automação: Pnl.Day (realizado de hoje), Open, DayWithOpen, Total, DayDrawdown e DayRunup. if (Pnl.DayWithOpen >= 500) ClosePosition(); |
IReadOnlyList<Trade> Trades | As operações fechadas pela automação (no backtest, todas; ao vivo, desde que o robô foi ligado). |
IReadOnlyList<Trade> TradesToday | As operações fechadas hoje. |
Trade? LastTrade | A última operação fechada; null se ainda não houve. |
int ConsecutiveWins | Fechamentos seguidos com ganho, hoje. |
Candle? CandleAgo(int barsAgo) | O candle barsAgo posições antes do atual (0 = o atual). Fora do histórico devolve null. |
CandleSeries Closes | Os fechamentos como série: Closes[1] é o do candle anterior (como close[1]). Closes.Average(20), Closes.Rising(3)... |
CandleSeries Opens | As aberturas como série. |
CandleSeries Highs | As máximas como série (Highs.Highest(20) = a maior máxima de 20 candles e há quantos foi). |
CandleSeries Lows | As mínimas como série. |
CandleSeries Volumes | Os volumes como série. |
static bool Na(double v) | O valor não é um número (NaN do aquecimento de um indicador, por exemplo). O na do Pine. |
static double Nz(double v, double fallback = 0) | O valor, ou fallback quando não é um número. O nz do Pine. |
virtual void OnFill(Fill fill) | Uma ordem do robô executou (inteira ou em parte): a mercado, pendente, stop/alvo do motor, regra, fim do dia. No backtest chega antes do OnBarClose do candle em que executou (ou logo depois dele, para a ordem do próprio candle); ao vivo, quando a corretora confirma. Aqui dá para pôr stop, alvo, pendentes e ordem a mercado (no backtest, a ordem a mercado pedida aqui executa no mesmo preço da execução que avisou). Só depois da zeragem do fim do dia não sai ordem a mercado (MERCADO_DEPOIS_DA_DECISAO). |
virtual void OnOrderRejected(PendingOrder order, string code, string message) | Uma ordem foi recusada: pelas regras da automação (horário, posição máxima...), pelo teto, pela conta ou pela corretora. |
virtual void OnOrderCanceled(PendingOrder order, string reason) | Uma pendente foi cancelada: pelo robô, por outra de mesmo nome, pelo motor (fim do dia, teto, encerramento, janela, saída pelo stop) ou de fora. |
void Buy(int quantity, string name, string? comment = null) | Compra a mercado com nome e comentário. |
void Sell(int quantity, string name, string? comment = null) | Vende a mercado com nome e comentário. |
void BuyLimit(int quantity, double price, string? name = null, string? comment = null) | Compra limitada (pendente). BuyLimit(1, Current.Low - 50, "pullback"); |
void SellLimit(int quantity, double price, string? name = null, string? comment = null) | Venda limitada (pendente). |
void BuyStop(int quantity, double stopPrice, string? name = null, string? comment = null) | Compra stop (pendente). BuyStop(1, Highs.Highest(20).Value + 5, "rompimento"); |
void SellStop(int quantity, double stopPrice, string? name = null, string? comment = null) | Venda stop (pendente). |
void BuyStopLimit(int quantity, double stopPrice, double limitPrice, string? name = null, string? comment = null) | Compra stop-limite (pendente; só no Simulador). |
void SellStopLimit(int quantity, double stopPrice, double limitPrice, string? name = null, string? comment = null) | Venda stop-limite (pendente; só no Simulador). |
bool Cancel(string name) | Cancela a pendente pelo nome. |
void CancelAll() | Cancela todas as pendentes. |
bool Modify(string name, double price) | Muda o preço (limite) ou o gatilho (stop) da pendente. |
void ClosePartial(int quantity) | Zera parte da posição a mercado. |
void Reverse() | Vira a mão a mercado. |
void TrailingStop(double points) | Stop móvel a N pontos. |
void BreakEven(double triggerPoints, double offsetPoints = 0) | Break-even: no gatilho (pontos a favor), o stop vai ao preço médio mais a folga. |
void StopLossAt(double price) | Stop num preço. |
void TakeProfitAt(double price) | Alvo num preço. |
IReadOnlyList<PendingOrder> PendingOrders | As pendentes de agora. |
IReadOnlyList<Candle> CandlesOf(string timeframe) | Os candles fechados de outro tempo do mesmo ativo (declare [UsesSeries("15m")]). var h = CandlesOf("60m"); |
IReadOnlyList<Candle> CandlesOf(string symbol, string timeframe) | Os candles fechados de outro ativo (declare [UsesSeries("WDOFUT", "5m")]; no backtest, a série pronta da tela). |
IReadOnlyList<Tick> RecentTicks | Os últimos negócios (até 500; só ao vivo). |
Aggression Aggression | A agressão desde que ligou (só ao vivo). |
double? Settlement | O ajuste do dia (só ao vivo; null sem o dado). |
O contexto do robô
IContext (interface)Tudo que o robô sabe e tudo que ele pode fazer chega por aqui. O robô nunca lê relógio, rede ou arquivo: o tempo e o preço são os do evento (o candle que fechou, ou o negócio) e a ordem vai para o motor, que decide o que executar. No backtest e ao vivo os comandos são os mesmos. ORDENS A MERCADO. Uma chamada do robô (OnBarClose, OnTick, OnBook, ou um evento de ordem que chega como chamada nova) pode mandar várias, até 20 (a 21ª é recusada: ORDENS_DEMAIS). Saem em sequência, e cada uma é conferida pela posição que as anteriores deixam (Buy(1); ClosePosition(); compra e zera; ClosePosition, ClosePartial e Reverse contam as ordens já pedidas na chamada). Ao vivo, entre uma chamada e a seguinte a entrada nova espera a anterior chegar à posição (ORDEM_EM_ANDAMENTO): nunca dobra a mão no escuro. Os eventos de ordem (OnFill, OnOrderRejected, OnOrderCanceled) também mandam a mercado; no backtest, no mesmo preço da decisão. Só depois da zeragem do fim do dia não sai ordem a mercado (MERCADO_DEPOIS_DA_DECISAO).
// Context é o que os atalhos do robô (Candles, Position, Buy...) usam por baixoLog($"candle {Context.Index + 1} de {Context.Candles.Count}, posição {Context.Position.Quantity}");if (Context.Position.IsFlat && Context.Current.IsBullish) Context.Buy(1);
| Membro | O que faz |
|---|---|
SymbolInfo SymbolInfo | O ativo e o contrato (tick, valor do ponto). |
IReadOnlyList<Candle> Candles | Candles fechados até agora, do mais antigo ao atual. O último é Current. |
Candle Current | O candle que acabou de fechar e motivou a chamada de OnBarClose. Em OnTick, o último candle FECHADO (o que está se formando não aparece, ao vivo e no backtest). |
int Index | Índice de Current em Candles. |
Timestamp Now | O momento DESTE evento, em Brasília (nunca o relógio do PC): no fechamento de candle, o FIM do candle (o de 5 min das 17:45 fecha às 17:50; com End, é ele); num negócio ou num book, a hora dele. Ao vivo, nunca volta: o candle que chega depois de um negócio mais novo (a última barra do pregão de um tempo como 45m, que só fecha no pregão seguinte; os tijolos que fecharam no mesmo minuto) fica com a hora desse negócio. |
Date Today | O pregão deste evento: a data do candle que fechou, ou a data do negócio/book. Ao vivo, o candle de um pregão que já passou (que chegou hoje) não volta o pregão: continua o de hoje. |
int SecondsPerCandle | A duração do candle em segundos (o tempo gráfico: 300 = 5 min, 7200 = 2 h). 0 nos gráficos atemporais (Renko, Range, Pontos, Ponto e figura, negócios, volume): a barra não tem duração fixa, e o End dela é o fim do minuto em que fechou (precisão de minuto; não quanto ela levou para se formar). Também 0 quando não deu para saber. |
Book Book | O book de agora (ao vivo); no backtest, Empty. |
Tick? LastTick | O último negócio visto (ao vivo). No backtest, o ponto sintético do OnTick (preço do ponto, quantidade 0, agressor Flat), ou null para o robô sem ele. |
Position Position | Posição líquida agora, depois das execuções do candle anterior. |
double DayProfit | Resultado realizado do dia (em dinheiro), já com corretagem no backtest. Ao vivo, o realizado do dia do robô na conta (Simulador ou MT5). |
double Equity | Patrimônio agora: inicial + realizado + aberto ao fechamento do candle atual. |
bool StoppedForDay | O robô encerrou o dia (stop diário, meta, perdas seguidas ou "zerar às"). Enquanto true, entradas são recusadas e o motor zera o que aparecer, até o próximo pregão. Saídas passam sempre. |
string? StopReason | Por que encerrou o dia (em palavras); null se não encerrou. |
AutomationRules Rules | As regras da automação: o motor vigia, o robô só lê. |
SessionState Session | O estado do pregão do ativo (ao vivo, informado pela bolsa); no backtest, Unknown. |
int? MinutesSinceOpen | Minutos desde o início do primeiro candle do dia até Now; null sem candle hoje. Nos gráficos atemporais o primeiro candle do dia é o minuto em que fechou a primeira barra de hoje (não a abertura do pregão). |
int EntriesToday | Entradas (a partir de zerada) que a automação fez hoje. |
int ConsecutiveLosses | Fechamentos seguidos com perda, hoje (um fechamento com ganho volta a zero). |
int ConsecutiveWins | Fechamentos seguidos com ganho, hoje (um fechamento com perda volta a zero). |
Pnl Pnl | O resultado da automação: dia, aberto, acumulado, drawdown e runup do dia. |
IReadOnlyList<Trade> Trades | As operações fechadas pela automação: todas no backtest; ao vivo, desde que o robô foi ligado. |
IReadOnlyList<Trade> TradesToday | As operações fechadas hoje. |
void Buy(int quantity) | Compra a mercado. No backtest executa no fechamento deste candle (em OnBarClose) ou no preço do ponto (em OnTick), mais o slippage configurado. Pode haver outras na mesma chamada (até 20, em sequência). |
void Sell(int quantity) | Vende a mercado. Como Buy, menos o slippage. |
void ClosePosition() | Zera a posição a mercado: a de agora mais as ordens a mercado já pedidas nesta chamada (Buy(1); ClosePosition(); zera a compra). Sem posição, não faz nada. |
void StopLoss(double points) | Stop de perda a points do preço médio da posição (a que existe ou a que esta decisão abrir). Executa como ordem a mercado no candle em que o preço tocar (com OnTick no backtest, no ponto em que tocar, a partir do seguinte), com slippage. Chamar de novo substitui o anterior; CancelStops remove. |
void TakeProfit(double points) | Alvo (realização) a points do preço médio, a favor. Executa no toque, sem slippage. |
void CancelStops() | Remove stop e alvo pendentes. |
void Log(string message) | Registro que aparece no painel do backtest e no diário do robô ao vivo. |
void Log(string message, LogLevel level) | Registro com nível: info, aviso ou erro colorem o diário; alerta é Alert. |
void Alert(string message) | Alerta: no HTS vira aviso na hora (toast, som e o sino de Avisos) e, no indicador no gráfico, uma seta com o texto acima do candle. |
void Plot(string name, double value, PlotStyle style = PlotStyle.Line) | Plota um valor da série name neste candle: é o que o gráfico desenha (indicador) e o que o painel do backtest mostra. Uma série, um valor por candle; chamar de novo no mesmo candle substitui. Candle sem chamada fica sem valor (buraco na linha). O estilo vale da primeira chamada da série. Valor não finito = sem valor. |
void Plot(string name, double value, string color) | Plota o valor com a cor DESTE ponto (cor por valor): Plot("sinal", v, v > 0 ? "#22c55e" : "#ef4444"). |
void StylePlot(string name, string? color, double width = 0) | A aparência padrão da série (cor e espessura); o gráfico ainda deixa trocar na "Aparência". |
void FillBetween(string seriesA, string seriesB, string? color = null) | Preenche a área entre duas séries plotadas (bandas, nuvem). color é a cor do preenchimento (com alfa, ex.: "rgba(120,120,255,0.1)"; sem alfa, a tela aplica transparência); a "Aparência" deixa trocar. |
void HLine(double value, string? color = null, string? text = null) | Uma linha horizontal no painel (70 e 30 do IFR, zero do MACD...), com texto opcional. |
void PaintCandle(string color) | Pinta o corpo do candle atual. |
void BackgroundColor(string color) | Pinta o fundo da coluna do candle atual. |
void Mark(string text, MarkerPosition position = MarkerPosition.Above, MarkerShape shape = MarkerShape.Arrow, string? color = null) | Uma marca no candle atual: seta, ponto ou só texto, acima da máxima ou abaixo da mínima. |
void Mark(string text, double value, MarkerPosition position = MarkerPosition.Above, MarkerShape shape = MarkerShape.Arrow, string? color = null) | Uma marca ancorada num valor (preço ou valor do painel). |
void DrawLine(int barsAgo1, double value1, int barsAgo2, double value2, string? color = null) | Uma linha de (candle barsAgo1 atrás, valor1) a (candle barsAgo2 atrás, valor2). 0 = o candle atual. |
void DrawBox(int barsAgo1, double value1, int barsAgo2, double value2, string? color = null) | Uma caixa com os mesmos cantos. |
void Table(int row, int column, string text) | Uma célula da tabela no canto do painel (até 10×10): números do robô que a pessoa quer ver. |
void Buy(int quantity, string name, string? comment = null) | Compra a mercado com nome (para os eventos) e comentário. |
void Sell(int quantity, string name, string? comment = null) | Vende a mercado com nome e comentário. |
void BuyLimit(int quantity, double price, string? name = null, string? comment = null) | Compra limitada a price (ou menos). No backtest executa no candle SEGUINTE em que a mínima tocar, sem slippage (abertura abaixo = executa na abertura). |
void SellLimit(int quantity, double price, string? name = null, string? comment = null) | Venda limitada a price (ou mais). |
void BuyStop(int quantity, double stopPrice, string? name = null, string? comment = null) | Compra stop: quando o preço chegar a stopPrice, compra a mercado (no backtest, com slippage; abertura acima = na abertura). |
void SellStop(int quantity, double stopPrice, string? name = null, string? comment = null) | Venda stop: quando o preço cair a stopPrice, vende a mercado. |
void BuyStopLimit(int quantity, double stopPrice, double limitPrice, string? name = null, string? comment = null) | Compra stop-limite: no stopPrice vira compra limitada a limitPrice (≥ gatilho). Só no Simulador (na conta MT5 o motor recusa com STOP_LIMITE_SO_SIMULADOR). No backtest, se o candle abrir acima do limite, a ordem vira limitada e só volta a ser conferida no candle seguinte. |
void SellStopLimit(int quantity, double stopPrice, double limitPrice, string? name = null, string? comment = null) | Venda stop-limite: no stopPrice vira venda limitada a limitPrice (≤ gatilho). |
bool Cancel(string name) | Cancela a pendente name. false = não há pendente com esse nome. |
void CancelAll() | Cancela todas as pendentes do robô. |
bool Modify(string name, double price) | Muda o preço da pendente name: na limitada, o limite; no stop, o gatilho; no stop-limite, o gatilho, e o limite anda junto (mantém a distância). false = não há pendente com esse nome. |
void ClosePartial(int quantity) | Zera PARTE da posição a mercado (só reduz: nunca vira a mão). Sem posição, não faz nada. |
void Reverse() | Vira a mão a mercado (comprado 2 → vendido 2). Cancela stop, alvo, stop móvel e break-even da posição velha e as pendentes de saída dela; o robô pede a proteção da posição nova na mesma chamada. Sem posição, não faz nada. |
void TrailingStop(double points) | Stop móvel a points: começa como StopLoss e anda a favor (comprado: a máxima menos os pontos), nunca contra. No backtest anda pela máxima/mínima de cada candle e vale a partir do candle seguinte; ao vivo, a cada negócio. CancelStops remove. |
void BreakEven(double triggerPoints, double offsetPoints = 0) | Break-even: quando o preço andar triggerPoints a favor do preço médio, o stop vai para o preço médio mais offsetPoints (a favor), se for melhor que o stop de agora. |
void StopLossAt(double price) | Stop de perda num PREÇO (não em pontos). Substitui o stop de agora. |
void TakeProfitAt(double price) | Alvo num PREÇO. Substitui o alvo de agora. |
IReadOnlyList<PendingOrder> PendingOrders | As pendentes do robô agora (fotografia; a ordem de colocação). |
IReadOnlyList<Candle> CandlesOf(string timeframe) | Os candles FECHADOS de outro tempo gráfico do mesmo ativo (declare [UsesSeries("15m")] na classe). O tempo do próprio robô devolve Candles. Sem a declaração, ou sem o dado, devolve vazio (e uma recusa SERIE_INDISPONIVEL, uma vez). |
IReadOnlyList<Candle> CandlesOf(string symbol, string timeframe) | Os candles FECHADOS de outro ativo (declare [UsesSeries("WDOFUT", "5m")]). No backtest, a série pronta que a tela manda (vazia sem histórico dela no período). |
IReadOnlyList<Tick> RecentTicks | Os últimos negócios (até 500, do mais antigo ao mais novo) desde que o robô ligou. Só ao vivo; no backtest, vazio. |
Aggression Aggression | A agressão (compra, venda, saldo) desde que o robô ligou. Só ao vivo; no backtest, Zero. |
double? Settlement | O ajuste do dia (futuros), quando a bolsa divulga. Só ao vivo; no backtest, null. |
API · Candles, séries e mercado
Candle
CandleUm candle fechado. Time é o início do candle em segundos Unix (UTC); a data e a hora em Brasília vêm por Timestamp. End é o fim, quando a barra traz (todos os tempos do gráfico, 01/11/2026).
// compra no candle de alta que fecha acima da máxima do anteriorif (Candles.Count < 2) return;var anterior = Candles[Candles.Count - 2];if (Position.IsFlat && Current.IsBullish && Current.Close > anterior.High) Buy(1);
| Membro | O que faz |
|---|---|
long Time | Início do candle, em segundos Unix (UTC). Nos gráficos atemporais (Renko, Range...), o minuto em que a barra FECHOU (veja End), não o começo dela. |
double Open | Preço de abertura, em pontos. |
double High | Preço máximo, em pontos. |
double Low | Preço mínimo, em pontos. |
double Close | Preço de fechamento, em pontos. |
double Volume | Volume negociado no candle, em contratos. |
long End | Fim do candle, em segundos Unix (UTC), exclusivo. Nos gráficos temporais o candle vale de Time até antes de End (o de 5 min das 10:00 termina às 10:05; a última barra do pregão pode ser mais curta). 0 quando a barra não diz; aí o fim é o início mais o tempo gráfico (SecondsPerCandle). Nos gráficos atemporais (Renko, Range, Pontos, Ponto e figura, negócios, volume) a barra não tem duração fixa, e End - Time NÃO diz quanto ela levou para se formar: ela é montada dos candles de 1 minuto, Time é o minuto em que ela fechou e End o fim desse minuto (precisão de minuto). As que fecham no mesmo minuto ficam 1 segundo uma depois da outra (a última vai até o fim do minuto). O tempo entre duas barras atemporais, com precisão de minuto, é a diferença entre os End delas. var fim = Current.End > 0 ? Current.End : Current.Time + SecondsPerCandle; // o fim da barra |
Timestamp Timestamp | Início do candle no horário de Brasília (Current.Timestamp.HHMM = 1005 no candle das 10:05). |
Date Date | A data (em Brasília) do candle. Dois candles com a mesma Date são do mesmo pregão. |
double Range | Amplitude do candle em pontos (máxima menos mínima). |
bool IsBullish | Candle que fechou acima de onde abriu. |
bool IsBearish | Candle que fechou abaixo de onde abriu. |
Negócio
TickUm negócio do mercado (ao vivo, cada negócio da bolsa; no backtest, um ponto da lupa de 1m). Aggressor é quem agrediu (comprador = Long); Flat = não informado.
public override void OnTick(Tick tick){ // lote grande comprando a mercado: entra junto if (Position.IsFlat && tick.Quantity >= 100 && tick.Aggressor == Side.Long) Buy(1);}
| Membro | O que faz |
|---|---|
long TimeMs | Instante do negócio, em milissegundos Unix (UTC). |
double Price | Preço do negócio, em pontos. |
int Quantity | Quantidade negociada, em contratos. |
Side Aggressor | Lado que agrediu; Flat quando não informado. |
Timestamp Timestamp | Instante em Brasília. |
Nível do book
BookLevelUm nível do book: preço, quantidade e número de ordens.
// melhor compra do book (ao vivo)if (Book.BestBid is BookLevel compra && compra.Quantity >= 500) Log($"{compra.Quantity} contratos em {compra.Price} ({compra.Orders} ordens)");
| Membro | O que faz |
|---|---|
double Price | Preço do nível, em pontos. |
int Quantity | Quantidade somada no nível, em contratos. |
int Orders | Número de ordens no nível. |
Book de ofertas
BookO book do ativo como chegou da bolsa: compras (do melhor para o pior) e vendas (do melhor para o pior). Vazio quando ainda não chegou nada. Só leitura: é uma fotografia.
public override void OnBook(Book book){ // só entra com spread de um tick e mais compradores que vendedores no topo if (book.Spread != SymbolInfo.TickSize || book.BestBid is not BookLevel compra || book.BestAsk is not BookLevel venda) return; if (Position.IsFlat && compra.Quantity > 2 * venda.Quantity) Buy(1);}
| Membro | O que faz |
|---|---|
static readonly Book Empty = new(Array.Empty<BookLevel>(), Array.Empty<BookLevel>()) | Book vazio: sem compras nem vendas. |
Book(IReadOnlyList<BookLevel> bids, IReadOnlyList<BookLevel> asks) | Monta o book com as compras e as vendas, cada lado do melhor para o pior preço. |
IReadOnlyList<BookLevel> Bids | Níveis de compra (bid), do melhor (maior preço) para o pior. |
IReadOnlyList<BookLevel> Asks | Níveis de venda (ask), do melhor (menor preço) para o pior. |
BookLevel? BestBid | Melhor compra (bid), ou null sem book. |
BookLevel? BestAsk | Melhor venda (ask), ou null sem book. |
double? Spread | Diferença entre a melhor venda e a melhor compra, em pontos; null sem os dois lados. |
Período (dia, semana, mês, ano)
Period (enum)Período de agregação dos candles.
// a semana até agora, a partir da lista de candlesif (Aggregates.UpToCandle(Candles, Candles.Count - 1, Period.Week) is Bar semana) Log($"semana: máxima {semana.High}, mínima {semana.Low}");
| Membro | O que faz |
|---|---|
Day | O dia (pregão). |
Week | A semana, começando na segunda-feira. |
Month | O mês civil. |
Year | O ano civil. |
Barra de um período
BarUm período inteiro resumido (o dia, a semana, o mês ou o ano), montado dos candles do robô: abertura do primeiro candle, máxima e mínima de todos, fechamento do último, volume somado (o OpenD/HighD/LowD/CloseD do NTSL).
// rompeu a máxima de ontem: compraif (PreviousDay is Bar ontem && Position.IsFlat && Current.Close > ontem.High) Buy(1);
| Membro | O que faz |
|---|---|
Timestamp Start | Início do período (início do primeiro candle), em Brasília. |
double Open | Abertura do primeiro candle, em pontos. |
double High | Maior máxima do período, em pontos. |
double Low | Menor mínima do período, em pontos. |
double Close | Fechamento do último candle, em pontos. |
double Volume | Volume somado do período, em contratos. |
int Candles | Quantos candles formam o período. |
double Range | Máxima menos mínima. |
Agregação por período
AggregatesAgregação de candles por período (no fuso de Brasília). Só faz contas sobre a lista de candles; não muda nada.
// linha na máxima da semana passadaif (Aggregates.Previous(Candles, Candles.Count - 1, Period.Week) is Bar semana) HLine(semana.High, "#ffffff", "máxima da semana passada");
| Membro | O que faz |
|---|---|
static Date PeriodKey(Date d, Period p) | A chave do período de um dia: dois candles com a mesma chave são do mesmo período. |
static Bar? UpToCandle(IReadOnlyList<Candle> candles, int index, Period p) | O período do candle index até ele (inclusive): o "dia até agora". |
static Bar? Previous(IReadOnlyList<Candle> candles, int index, Period p) | O período ANTERIOR ao do candle index, inteiro (o "dia de ontem"); null se não está no histórico. |
static bool IsFirstOfDay(IReadOnlyList<Candle> candles, int index) | O candle index é o primeiro do seu dia no histórico. |
Série
ISeries (interface)Uma série alinhada aos candles: serie[0] é o valor de agora, serie[1] o do candle anterior (como close[1] no Pine). Fora do histórico, NaN. Todo indicador é uma série; o robô cria as suas com Series; os candles aparecem como séries em Closes, Highs etc. Os utilitários (Ta) valem para qualquer uma.
private static bool SubindoHa3(ISeries s) => s[0] > s[1] && s[1] > s[2];public override void OnBarClose(){ // a mesma função serve para Closes, Highs, um indicador ou uma Series sua if (Position.IsFlat && SubindoHa3(Closes) && SubindoHa3(Lows)) Buy(1);}
| Membro | O que faz |
|---|---|
double this[int barsAgo] | O valor barsAgo candles antes do atual (0 = atual). Fora do histórico, NaN. |
int Count | Quantos valores existem. |
Série própria
SeriesUma série que o próprio robô alimenta, um valor por candle (Add em OnBarClose).
private readonly Series _corpo = new();public override void OnBarClose(){ // corpo do candle duas vezes maior que a média dos últimos 20: alerta _corpo.Add(Math.Abs(Current.Close - Current.Open)); if (_corpo.Count > 20 && _corpo.Value > 2 * _corpo.Average(20)) Alert("candle de força");}
| Membro | O que faz |
|---|---|
double this[int barsAgo] | O valor barsAgo candles antes do atual (0 = atual). Fora do histórico, NaN. |
int Count | Quantos valores já foram acrescentados. |
double Value | O valor de agora (NaN sem valor). |
double Previous | O valor do candle anterior. |
double Add(double value) | Acrescenta o valor deste candle e o devolve. |
void ReplaceLast(double value) | Troca o valor de agora (o último) sem avançar: para recalcular dentro do mesmo candle. |
Série de sim ou não
BoolSeriesUma série de sim/não alinhada aos candles (Add(cruzou) por candle): responde "há quantos candles foi a última vez" (BarsSince) e "qual era o valor de outra série da última vez" (ValueWhen).
private readonly BoolSeries _rompeu = new();public override void OnBarClose(){ // só compra até 3 candles depois de romper a máxima anterior _rompeu.Add(Current.Close > Highs[1]); if (Position.IsFlat && _rompeu.BarsSince() is int n && n <= 3 && Current.IsBullish) Buy(1);}
| Membro | O que faz |
|---|---|
bool this[int barsAgo] | O valor barsAgo candles antes do atual (0 = atual). Fora do histórico, false. |
int Count | Quantos valores já foram acrescentados. |
bool Value | O valor de agora (false sem valor). |
bool Add(bool value) | Acrescenta o valor deste candle e o devolve. |
int? BarsSince() | Candles desde a última vez verdadeira (0 = agora); null se nunca foi. |
double ValueWhen(ISeries series, int occurrence = 0) | O valor de series na occurrence-ésima vez (0 = a última) em que o marcador foi verdadeiro; NaN se não houve. |
Candles como série
CandleSeriesOs candles vistos como série de um campo (Closes[1]), presos ao índice do candle atual.
// Closes[0] é o fechamento atual, Closes[1] o do candle anteriorif (Position.IsFlat && Closes[0] > Closes.Average(20) && Closes.Rising(3)) Buy(1);if (Position.IsLong && Closes[0] < Lows[1]) ClosePosition();
| Membro | O que faz |
|---|---|
double this[int barsAgo] | O campo do candle barsAgo candles antes do atual (0 = atual). Fora do histórico, NaN. |
int Count | Quantos candles existem até o atual (inclusive). |
double Value | O campo do candle atual. |
double Previous | O campo do candle anterior. |
Contas de série
TaOs utilitários de série (o que o Pine tem em ta.* e math.*); NaN quando falta número.
// fechou dois desvios abaixo da média de 20: compra (retorno à média)var media = Ta.Average(Closes, 20);var desvio = Closes.StdDev(20);if (Position.IsFlat && Current.Close < media - 2 * desvio) Buy(1);
| Membro | O que faz |
|---|---|
static double Sum(this ISeries s, int n) | A soma dos últimos n valores (contando o atual). |
static double Average(this ISeries s, int n) | A média dos últimos n valores. |
static double StdDev(this ISeries s, int n) | O desvio padrão (populacional, como ta.stdev) dos últimos n valores. |
static bool Rising(this ISeries s, int n = 1) | Subiu n candles seguidos (cada valor maior que o anterior). |
static bool Falling(this ISeries s, int n = 1) | Caiu n candles seguidos (cada valor menor que o anterior). |
static double Change(this ISeries s, int n = 1) | A variação em n candles: valor de agora menos o de n atrás. |
static double PercentChange(this ISeries s, int n = 1) | A variação em n candles, em porcentagem do valor de antes. |
static double Percentile(this ISeries s, int n, double p) | O percentil p (0 a 100, interpolado) dos últimos n valores. |
static double Correlation(this ISeries a, ISeries b, int n) | A correlação de Pearson entre as duas séries nos últimos n candles (−1 a 1). |
Valor inválido (NaN)
NumNúmeros com NaN (o na/nz do Pine): o aquecimento dos indicadores é NaN.
// no começo do histórico ainda não há 50 candles: a média vem NaNvar media = Closes.Average(50);if (Num.Na(media)) Log("média de 50 ainda aquecendo");// Nz troca o NaN por outro valor (aqui, o fechamento)Plot("Média 50", Num.Nz(media, Current.Close));
| Membro | O que faz |
|---|---|
static bool Na(double v) | O valor não é um número (NaN ou infinito). |
static double Nz(double v, double fallback = 0) | O valor, ou fallback quando não é um número. |
API · Posição e ordens
Lado
Side (enum)Lado de uma posição ou de uma ordem.
// vendido e o candle fechou de alta: saiif (Position.Side == Side.Short && Current.IsBullish) ClosePosition();
Posição
PositionA posição líquida do robô no ativo (netting, como na B3): uma quantidade com sinal e o preço médio. Quantidade positiva é comprado, negativa é vendido, zero é zerado.
// comprado com 200 pontos a favor: realiza metadeif (Position.IsLong && Position.Contracts >= 2 && Current.Close - Position.AveragePrice >= 200) ClosePartial(Position.Contracts / 2);Log($"aberto: R$ {Position.OpenProfit(Current.Close, SymbolInfo):0.00}");
| Membro | O que faz |
|---|---|
int Quantity | Quantidade com sinal, em contratos: positiva comprado, negativa vendido, zero zerado. |
double AveragePrice | Preço médio da posição, em pontos; 0 quando zerado. |
static readonly Position Flat = new(0, 0) | Posição zerada. |
Side Side | O lado da posição: comprado, vendido ou zerado. |
bool IsFlat | Está zerado (quantidade zero). |
bool IsLong | Está comprado (quantidade positiva). |
bool IsShort | Está vendido (quantidade negativa). |
int Contracts | Quantidade sem sinal. |
double OpenPoints(double price) | Resultado aberto a um preço, em pontos por contrato vezes a quantidade (sem converter em dinheiro). |
double OpenProfit(double price, SymbolInfo symbolInfo) | Resultado aberto em dinheiro, pela especificação do contrato. |
Tipo de ordem
OrderType (enum)O tipo de uma ordem do robô. A mercado executa já; as outras ficam PENDENTES até o preço chegar (no dia).
// já tem compra limitada no livro: não põe outraif (PendingOrders.Any(o => o.Type == OrderType.Limit && o.Side == Side.Long)) return;BuyLimit(1, Current.Low - 50, "pullback");
| Membro | O que faz |
|---|---|
Market | A mercado (Buy, Sell, ClosePosition, ClosePartial, Reverse). |
Limit | Limitada: compra a Price ou menos; vende a ele ou mais. Sem slippage. |
Stop | Stop (de entrada ou de saída): o preço tocou o StopPrice, vira ordem a mercado. |
StopLimit | Stop-limite: o preço tocou o gatilho, vira limitada no Price. Só no Simulador (a MT5 recusa). |
Ordem pendente
PendingOrderUma ordem do robô: a pendente que está no livro (PendingOrders) ou a ordem dos eventos OnOrderRejected/OnOrderCanceled. Name é o que o robô deu (ou o automático, "limite-1", "stop-2"...); a ordem a mercado sem nome vem com "". Price é o limite (limitada e stop-limite) e StopPrice o disparo (stop e stop-limite). ReduceOnly: a ordem só diminui a posição que existia quando foi colocada (uma saída); se a posição zerar, ela cai.
public override void OnOrderCanceled(PendingOrder order, string reason){ // registra qual pendente caiu e por quê Log($"{order.Name}: {order.Quantity} a {order.Price ?? order.StopPrice} cancelada ({reason})");}
| Membro | O que faz |
|---|---|
string Name | Nome da ordem (o dado pelo robô ou o automático); "" na ordem a mercado sem nome. |
Side Side | Lado: Long compra, Short vende. |
int Quantity | Quantidade, em contratos. |
OrderType Type | Tipo da ordem. |
double? Price | Preço limite, em pontos (limitada e stop-limite); null nos outros tipos. |
double? StopPrice | Preço de disparo, em pontos (stop e stop-limite); null nos outros tipos. |
bool ReduceOnly | A ordem só diminui a posição (uma saída); cai se a posição zerar. |
string? Comment = null | Comentário livre dado pelo robô; null sem comentário. |
Execução
FillUma execução de ordem do robô, entregue em OnFill. Source diz quem mandou: "robo" (a mercado), "stop"/"alvo" (a proteção do motor), "limite", "stop_pendente" e "stop_limite" (as pendentes), "regra", "teto_diario", "fim_do_dia", "fim". Name e Comment são os da ordem (vazio sem nome). No backtest o instante é o INÍCIO do candle em que executou (como as execuções do relatório), ou a hora do ponto quando executou na lupa do OnTick; ao vivo, a hora que a corretora informou.
public override void OnFill(Fill fill){ // a limitada de entrada executou: põe stop e alvo if (fill.Source == "limite") { StopLoss(150); TakeProfit(300); } Log($"executou {fill.Quantity} a {fill.Price} às {fill.Time.HHMM}");}
| Membro | O que faz |
|---|---|
Timestamp Time | Instante da execução, em Brasília. |
Side Side | Lado executado: Long comprou, Short vendeu. |
int Quantity | Quantidade executada, em contratos. |
double Price | Preço da execução, em pontos. |
string Source | Quem mandou a ordem ("robo", "stop", "alvo", "limite", "regra"...). |
string Name = "" | Nome da ordem; "" sem nome. |
string? Comment = null | Comentário da ordem; null sem comentário. |
Agressão
AggressionA agressão desde que o robô ligou (só ao vivo): contratos negociados com o comprador agredindo (Buy) e com o vendedor agredindo (Sell). Negócio sem agressor informado não conta. No backtest é sempre Zero (o candle não diz quem agrediu).
// comprador agredindo bem mais que o vendedor (ao vivo)if (Position.IsFlat && Aggression.Delta > 500) Buy(1);Log($"compra {Aggression.Buy}, venda {Aggression.Sell}");
| Membro | O que faz |
|---|---|
long Buy | Contratos negociados com o comprador agredindo. |
long Sell | Contratos negociados com o vendedor agredindo. |
static readonly Aggression Zero = new(0, 0) | Sem agressão nenhuma (compra e venda zeradas). |
long Delta | Compra menos venda: positivo = mais agressão de compra. |
Usar outra série
UsesSeriesAttributeDeclara uma série extra que o robô lê com CandlesOf: outro tempo gráfico do mesmo ativo ([UsesSeries("15m")]) ou outro ativo ([UsesSeries("WDOFUT", "5m")]). Tempos: os temporais do gráfico, em minutos (1m a 1439m: 1m, 2m, 5m, 10m, 45m...), em horas (1h a 23h: 2h, 3h, 4h...) ou D; "120m" e "2h" são a mesma série. Séries atemporais (Renko, Range...) ainda não. Até 4 séries e 2 ativos extras por robô. Ao vivo, o robô recebe o histórico e cada candle fechado dessas séries. No backtest (e no indicador do gráfico), a tela manda a série PRONTA, com as barras do gráfico daquele tempo, só as que já fecharam, sempre que o motor não a monta igual dos candles do teste: outro ativo, teste atemporal, tempo que não é múltiplo do tempo do teste e, num teste contado (2m, 10m, 45m...), a série de outra base (2m pedindo 30m). A barra pronta aparece no candle do teste que termina quando ela já terminou (a curta do fim do pregão do mesmo ativo, num teste temporal, no último candle do dia). Outro tempo do MESMO ativo, múltiplo do tempo do teste, é montado dos candles do teste pela regra do gráfico: 5m, 15m, 30m e 60m alinhados ao relógio, como o banco guarda; os outros juntam esses candles contando do início de cada pregão (45m = três de 15m). Sem histórico da série no período do teste (ou com a declaração feita com uma constante, que a tela não lê: escreva o texto), ela fica vazia no backtest, com a recusa SERIE_INDISPONIVEL e o motivo.
[UsesSeries("60m")]public class ATendenciaDo60 : Robot{ public override void OnBarClose() { // só compra a favor do último candle de 60 minutos var h60 = CandlesOf("60m"); if (h60.Count > 0 && h60[h60.Count - 1].IsBullish && Position.IsFlat && Current.IsBullish) Buy(1); }}
| Membro | O que faz |
|---|---|
UsesSeriesAttribute(string timeframe) | Outro tempo gráfico do mesmo ativo do robô. |
UsesSeriesAttribute(string symbol, string timeframe) | Outro ativo (no tempo gráfico timeframe). |
string? Symbol | O ativo; null = o do robô. |
string Timeframe | O tempo gráfico: minutos (1m a 1439m), horas (1h a 23h) ou D. |
static readonly IReadOnlyList<string> Timeframes = new[] | Os tempos que o banco guarda (1m, 5m, 15m, 30m, 60m e D). Os outros temporais (2m, 45m, 2h...) também valem: são montados destes, como no gráfico (Seconds diz se um texto vale). |
const int MaxSeries = 4 | Quantas séries extras um robô declara, no máximo, e quantos ativos além do dele. |
const int MaxExtraSymbols = 2 | Quantos ativos além do próprio um robô pode declarar, no máximo. |
static int Seconds(string? timeframe) | A duração do tempo gráfico em segundos (5m = 300, 2h = 7200, D = 86400); 0 para um texto que não é um tempo: minutos de 1 a 1439 ("45m"), horas de 1 a 23 ("2h") ou "D". Sem zero à esquerda; "m" e "h" minúsculos. |
API · Ativo, tempo e calendário
Dados do ativo
SymbolInfoO que o motor precisa saber do contrato para transformar pontos em dinheiro: o tamanho do tick e quanto vale um ponto por contrato. Os números dos futuros da B3 são os mesmos que a plataforma usa no resto do HTS.
// quanto custa um stop de 150 pontos em 2 contratos deste ativovar risco = SymbolInfo.ToMoney(150, 2);Log($"{SymbolInfo.Symbol}: risco de R$ {risco:0.00}");BuyLimit(2, SymbolInfo.RoundToTick(Current.Low - 0.3 * Current.Range), "pullback");
| Membro | O que faz |
|---|---|
string Symbol | Código do ativo (WINZ26, WDOFUT, PETR4...). |
double TickSize | Menor variação de preço, em pontos (5 no WIN, 0,5 no WDO). |
double PointValue | Quanto vale um ponto por contrato, em reais (0,2 no WIN, 10 no WDO). |
string Currency = "BRL" | Moeda do resultado; "BRL" por padrão. |
static SymbolInfo? FromB3(string symbol) | Especificação dos futuros mais operados pela raiz do símbolo (WIN, WDO, IND, DOL) e das ações da B3 (4 letras + 3/4/5/6/7/8/11, com ou sem o F do fracionário: R$ 0,01 de tick, R$ 1 por ponto por ação), a mesma regra da tela de backtest. Outro símbolo devolve null: o motor exige a especificação explícita, nunca chuta. |
double RoundToTick(double price) | Arredonda um preço para o múltiplo do tick mais próximo. |
double ToMoney(double points, int quantity) | Quanto vale, em dinheiro, uma diferença de points em quantity contratos. |
Dia da semana
Weekday (enum)Dia da semana, de domingo (0) a sábado (6).
// sexta-feira zera mais cedoif (Today.Weekday == Weekday.Friday && Now.HHMM >= 1700) ClosePosition();
Data
DateUma data do calendário (sem hora), no horário de Brasília. É o "pregão" de um candle: dois candles com o mesmo Date são do mesmo dia. Compara com <, > e ==.
// no dia do vencimento do contrato não operavar vencimento = B3Calendar.Expiration(SymbolInfo.Symbol);if (vencimento == Today) return;if (Today.Weekday == Weekday.Monday && Today.Day <= 7) Log("primeira segunda-feira do mês");
| Membro | O que faz |
|---|---|
int Year | Ano com quatro dígitos. |
int Month | Mês, de 1 a 12. |
int Day | Dia do mês, de 1 a 31. |
Weekday Weekday | O dia da semana desta data. |
bool IsWeekend | Sábado ou domingo. |
bool IsBusinessDay | Dia útil da B3 (sem fim de semana e sem feriado de pregão). Ver B3Calendar. |
int WeekOfYear | A semana do ano (ISO 8601: a semana começa na segunda; a semana 1 tem a primeira quinta-feira do ano). |
int DayOfYear | O dia do ano (1 a 366). |
Date AddDays(int days) | A data days dias corridos depois (negativo = antes). |
Date AddMonths(int months) | A mesma data months meses depois (o dia é ajustado ao fim do mês quando precisa). |
int DaysUntil(Date other) | Dias corridos até other (negativo se other é antes). |
Date StartOfMonth | O primeiro dia do mês desta data. |
Date EndOfMonth | O último dia do mês desta data. |
Date StartOfWeek | A segunda-feira da semana desta data. |
int CompareTo(Date other) | Compara com outra data: negativo se esta é antes, zero se é a mesma, positivo se é depois. |
override string ToString() | "dd/MM/aaaa". |
string Iso | "aaaa-MM-dd" (formato ISO). |
static Date? FromIso(string? text) | Lê "aaaa-MM-dd"; null se não é uma data válida. |
Instante
TimestampUm instante, mostrado no horário de Brasília (com o horário de verão de 2008 a 2019, para o backtest antigo; sem horário de verão desde 2019). O robô não lê relógio: o instante vem SEMPRE do mercado — o início ou o fim de um candle, a hora de um negócio. Ver Now e Timestamp.
// zera às 17:50 e não abre antes das 9:15if (Now.HHMM >= 1750) { ClosePosition(); return; }if (Now.HHMM < 915) return;
| Membro | O que faz |
|---|---|
long Milliseconds | O instante em milissegundos Unix (UTC). |
static Timestamp FromSeconds(long unixSeconds) | A partir de segundos Unix (UTC) — o Time do candle. |
Date Date | A data (em Brasília). |
int Year | O ano, em Brasília. |
int Month | O mês (1 a 12), em Brasília. |
int Day | O dia do mês (1 a 31), em Brasília. |
int Hour | A hora (0 a 23), em Brasília. |
int Minute | O minuto (0 a 59). |
int Second | O segundo (0 a 59). |
Weekday Weekday | O dia da semana, em Brasília. |
int HHMM | Hora e minuto num número: 9:05 = 905, 17:50 = 1750 (o Time do NTSL). |
int MinuteOfDay | Minutos desde a meia-noite (0 a 1439). |
long UnixSeconds | Segundos Unix (UTC), o mesmo número do Time do candle. |
bool Between(int hhmmStart, int hhmmEnd) | Entre dois horários do dia, em HHMM: inclui o início e exclui o fim (Between(900, 1200) = das 9h às 11:59). |
Timestamp AddSeconds(long seconds) | O instante seconds segundos depois (negativo = antes). |
Timestamp AddMinutes(long minutes) | O instante minutes minutos depois (negativo = antes). |
long MinutesUntil(Timestamp other) | Minutos (inteiros) até other; negativo se for antes. |
int CompareTo(Timestamp other) | Compara com outro instante: negativo se este é antes, zero se é o mesmo, positivo se é depois. |
override string ToString() | "dd/MM/aaaa HH:mm:ss". |
Calendário da B3
B3CalendarO calendário de pregão da B3: dias úteis, feriados e vencimentos. Os feriados seguem a regra oficial (Ofício Circular da B3 de cada ano): os nacionais fixos, Carnaval (segunda e terça), Sexta-feira Santa e Corpus Christi (pela Páscoa), Consciência Negra (20/11, desde 2024), e os dias sem sessão de 24/12 e 31/12. Os feriados municipais de São Paulo (25/01, 09/07) têm pregão desde 2022. Quarta-feira de Cinzas tem pregão, a partir das 13h.
if (!Today.IsBusinessDay) return;var du = B3Calendar.BusinessDaysBetween(Today, B3Calendar.Expiration("WINZ26")!.Value);if (du <= 1) { ClosePosition(); return; } // não carregar no dia do vencimento
| Membro | O que faz |
|---|---|
static string? HolidayName(Date d) | O nome do feriado (ou dia sem pregão) nesta data; null se não é feriado. Fim de semana não é feriado. |
static bool IsBusinessDay(Date d) | Dia com pregão: não é fim de semana nem feriado. |
static Date NextBusinessDay(Date d) | O primeiro dia útil DEPOIS de d. |
static Date PreviousBusinessDay(Date d) | O último dia útil ANTES de d. |
static Date BusinessDayOrNext(Date d) | d se for dia útil; senão, o próximo dia útil. |
static int BusinessDaysBetween(Date from, Date until) | Dias úteis entre duas datas, como no mercado (ANBIMA): conta from e não conta until. Do mesmo dia = 0; de hoje até amanhã útil = 1. Negativo se until é antes. |
static Date? NthBusinessDayOfMonth(int year, int month, int n) | O n-ésimo dia útil do mês (1 = o primeiro); null se o mês não tem tantos. |
static Date LastBusinessDayOfMonth(int year, int month) | O último dia útil do mês. |
static int? SpecialOpening(Date d) | A abertura especial do dia em HHMM (Quarta-feira de Cinzas: 1300); null = horário normal. |
static Date? Expiration(string symbol) | O vencimento de um contrato futuro da B3 pelo código (WINZ26, WDOX26, INDZ26, DOLX26, DI1F27); null se o ativo não é um desses ou o código não tem mês/ano. WIN e IND (meses pares): a quarta-feira mais próxima do dia 15; se não for dia útil, o próximo dia útil; WDO, DOL e DI1: o primeiro dia útil do mês do contrato. |
static int? BusinessDaysToExpiration(string symbol, Date today) | Dias úteis de today até o vencimento do contrato (0 = vence hoje); null se não se sabe o vencimento. |
static string? CurrentContract(string root, Date today) | O código do contrato vigente de uma raiz ("WIN", "WDO"...) numa data: o primeiro que vence DEPOIS dela — no dia do vencimento a plataforma já vira para o próximo. Ex.: CurrentContract("WIN", new Date(2026, 10, 30)) = "WINZ26". |
static Date? NextExpiration(string root, Date today) | O vencimento do contrato vigente da raiz ("WIN", "WDO"...) numa data: a data em que ele vence, sempre DEPOIS de today. null se a raiz não é conhecida. |
const string MonthLetters = "FGHJKMNQUVXZ" | F G H J K M N Q U V X Z = janeiro a dezembro (o padrão da B3). |
static Date Easter(int year) | O domingo de Páscoa do ano (algoritmo de Meeus/Jones/Butcher, calendário gregoriano). |
API · Regras e resultado
Estado do pregão
SessionState (enum)O estado do pregão do ativo, informado pela bolsa (ao vivo). No backtest é sempre Unknown.
// em leilão não abre posiçãoif (Session == SessionState.Auction) return;if (Position.IsFlat && Current.IsBullish) Buy(1);
| Membro | O que faz |
|---|---|
Unknown | Estado não informado (sempre assim no backtest). |
Open | Pregão aberto, em negociação contínua. |
Auction | Leilão: de abertura, intradiário ou de fechamento. |
Closed | Pregão fechado: sem negociação. |
Regras da automação
AutomationRulesAs regras da automação, escolhidas na tela "Meus robôs" e vigiadas pelo MOTOR: o robô lê (Rules), mas não precisa nem consegue burlar. Regra nunca bloqueia saída. Horário em HHMM de Brasília (1740 = 17:40); dinheiro em reais; null = sem a regra. StartTime/NoEntryAfter: a janela de entrada; FlattenAt: zera e encerra o dia; PauseInAuction: não abre com o ativo em leilão; WaitAfterOpen: não abre nos primeiros N minutos do pregão (desde o primeiro candle do dia); DailyTarget/DailyStop: realizado + aberto do dia atinge → zera e encerra o dia; MaxConsecutiveLosses: N fechamentos seguidos com perda → zera e encerra o dia; MaxEntriesPerDay: entradas (a partir de zerada) por dia; MaxPosition: contratos, em módulo.
// fora da janela de entrada da tela, nem tentaif (!Rules.CanEnterAt(Now.HHMM) || !Rules.OpeningWaitPassed(MinutesSinceOpen)) return;var maximo = Rules.MaxPosition ?? 1;if (Position.Contracts < maximo && Current.IsBullish) Buy(1);
| Membro | O que faz |
|---|---|
int? StartTime = null | Início da janela de entrada, em HHMM de Brasília; null sem a regra. |
int? NoEntryAfter = null | Não abre posição a partir deste horário, em HHMM de Brasília; null sem a regra. |
int? FlattenAt = null | Zera e encerra o dia neste horário, em HHMM de Brasília; null sem a regra. |
bool PauseInAuction = false | Não abre posição com o ativo em leilão. |
double? DailyTarget = null | Meta do dia, em reais (realizado + aberto); null sem a regra. |
double? DailyStop = null | Stop do dia, em reais (realizado + aberto); null sem a regra. |
int? MaxConsecutiveLosses = null | Fechamentos seguidos com perda que encerram o dia; null sem a regra. |
int? MaxEntriesPerDay = null | Entradas (a partir de zerado) permitidas por dia; null sem a regra. |
int? MaxPosition = null | Posição máxima, em contratos (em módulo); null sem a regra. |
int? WaitAfterOpen = null | Minutos sem abrir posição depois do primeiro candle do dia; null sem a regra. |
static readonly AutomationRules None = new() | Sem nenhuma regra. |
bool CanEnterAt(int hhmm) | O horário hhmm está dentro da janela de entrada (início, não abrir depois, zerar às). |
bool OpeningWaitPassed(int? minutesSinceOpen) | Já passou a espera da abertura. minutesSinceOpen null (nenhum candle hoje) não passa: sem saber a abertura, não abre. |
Operação fechada
TradeUma operação fechada (de zerado a zerado, ou até a virada de mão). Tempos em segundos Unix. Dinheiro pela especificação do contrato; Mfe/Mae são a maior excursão a favor (≥ 0) e contra (≤ 0) enquanto a operação esteve aberta (pela máxima/mínima dos candles no backtest; pelos negócios ao vivo).
// depois de uma perda, espera o próximo candle de alta para voltarvar ultima = LastTrade;if (ultima is not null && ultima.Profit < 0 && !Current.IsBullish) return;if (ultima is not null) Log($"última: {ultima.Points} pontos, R$ {ultima.Profit:0.00}");
| Membro | O que faz |
|---|---|
long EntryTime | Instante da entrada, em segundos Unix. |
long ExitTime | Instante da saída, em segundos Unix. |
Side Side | Lado da operação: Long comprada, Short vendida. |
int Contracts | Quantidade da operação, em contratos. |
double EntryPrice | Preço médio de entrada, em pontos. |
double ExitPrice | Preço médio de saída, em pontos. |
double GrossProfit | Resultado antes da corretagem, em reais. |
double Commission | Corretagem da operação, em reais. |
double Profit | Resultado líquido (bruto menos corretagem), em reais. |
string ExitReason | Motivo da saída (quem mandou a ordem que zerou). |
double Mfe = 0 | Maior excursão a favor enquanto aberta, em reais (≥ 0). |
double Mae = 0 | Maior excursão contra enquanto aberta, em reais (≤ 0). |
double Points | Pontos por contrato no sentido da operação (positivo = ganhou). |
Resultado da automação
PnlO resultado da automação, só leitura. Day é o realizado de hoje (no backtest já com corretagem; ao vivo, o realizado do robô na conta); Open é a posição ao preço de agora; Total é o realizado desde o início (do backtest; ao vivo, desde que o robô foi ligado). Drawdown e runup são a maior queda e a maior subida de DayWithOpen no dia, em dinheiro (≥ 0).
// ganhou R$ 300 no dia (realizado + aberto): zera e para de entrarif (Pnl.DayWithOpen >= 300) { ClosePosition(); return; }Log($"dia: R$ {Pnl.Day:0.00}, aberto: R$ {Pnl.Open:0.00}");
| Membro | O que faz |
|---|---|
double Day | Realizado de hoje, em reais. |
double Open | Resultado da posição aberta ao preço de agora, em reais. |
double Total | Realizado desde o início, em reais. |
double DayDrawdown | Maior queda do realizado + aberto no dia, em reais (≥ 0). |
double DayRunup | Maior subida do realizado + aberto no dia, em reais (≥ 0). |
static readonly Pnl Zero = new(0, 0, 0, 0, 0) | Resultado zerado em todos os campos. |
double DayWithOpen | Realizado do dia mais o aberto: é o que a meta e o stop diário olham. |
API · Gráfico
Estilo do desenho
PlotStyle (enum)Como uma série plotada por Plot é desenhada no gráfico. A cor padrão pode vir do código (StylePlot), e o gráfico deixa trocar na "Aparência".
// volume como histograma e a média dele como linhaPlot("Volume", Current.Volume, PlotStyle.Histogram);Plot("Volume médio", Volumes.Average(20), PlotStyle.Line);
| Membro | O que faz |
|---|---|
Line | Linha contínua ligando os valores (o padrão). |
Histogram | Histograma: uma barra por candle. |
Points | Um ponto em cada candle com valor. |
Area | Linha com a área até a base preenchida. |
Step | Linha em degraus (o valor vale até o próximo candle). |
Cross | Uma cruz em cada candle com valor. |
Columns | Colunas a partir do zero, na largura do candle. |
Posição da marca
MarkerPosition (enum)Onde a marca fica em relação ao candle.
// seta verde abaixo do candle que rompeu a máxima anteriorif (Current.Close > Highs[1]) Mark("rompeu", MarkerPosition.Below, MarkerShape.Arrow, "#22c55e");
| Membro | O que faz |
|---|---|
Above | Acima da máxima (ou do valor dado). |
Below | Abaixo da mínima (ou do valor dado). |
Forma da marca
MarkerShape (enum)A forma da marca: seta apontando para o candle, ponto, ou só o texto.
// ponto acima de todo candle sem corpo (doji)if (Math.Abs(Current.Close - Current.Open) <= SymbolInfo.TickSize) Mark("doji", MarkerPosition.Above, MarkerShape.Dot);
| Membro | O que faz |
|---|---|
Arrow | Seta apontando para o candle. |
Dot | Um ponto. |
Text | Só o texto, sem forma. |
Nível do registro
LogLevel (enum)O nível de um registro do robô: Info é o Log de sempre; Alert é o Alert(...), que no HTS vira aviso na tela (toast, som e sino) e marca no gráfico.
// perto do stop diário: registra como avisoif (Pnl.DayWithOpen < -200) Log("perto do stop diário", LogLevel.Warning);
| Membro | O que faz |
|---|---|
Info | Informação: o Log de sempre. |
Warning | Aviso: algo merece atenção, mas o robô segue. |
Error | Erro registrado pelo robô. |
Alert | Alerta (Alert(...)): aviso na tela (toast, som e sino) e marca no gráfico. |
Sobre o preço
OverlayAttributeNa classe do indicador: as séries plotadas vão SOBRE o preço (média, banda, VWAP), na escala do preço. Sem o atributo, o indicador ganha um painel próprio com escala livre (MACD, RSI, oscilador).
[Overlay]public class MediaDe20 : Robot{ // a média aparece em cima dos candles, na escala do preço public override void OnBarClose() => Plot("Média 20", Closes.Average(20));}
API · Parâmetros
Formato do parâmetro
ParameterFormat (enum)O formato de um parâmetro de texto ou de hora: diz à tela que campo mostrar e ao motor o que aceitar. Time vale para int (HHMM, 1740 = 17:40; a tela mostra HH:MM); os outros para string.
[Parameter("Zerar às", Format = ParameterFormat.Time)] public int ZerarAs = 1740;[Parameter("Cor da média", Format = ParameterFormat.Color)] public string Cor = "#22c55e";public override void OnBarClose(){ if (Now.HHMM >= ZerarAs) ClosePosition(); Plot("Média 20", Closes.Average(20), Cor);}
| Membro | O que faz |
|---|---|
Default | O campo comum do tipo (número, caixa de marcar, texto ou lista). |
Time | int em HHMM; a tela digita HH:MM. |
Color | string com cor #rrggbb; a tela mostra o seletor de cor. |
Symbol | string com o código do ativo (WINZ26, WDOFUT); a tela mostra a busca de ativo. |
Timeframe | string com o tempo gráfico (1m, 5m, 15m, 30m, 60m, D); a tela mostra a lista. |
Parâmetro
ParameterAttributeMarca um campo ou propriedade pública do robô como parâmetro ajustável pela tela, dentro dos limites definidos aqui. Tipos aceitos: int, double, bool, string (texto; com Options vira lista) e qualquer enum seu (lista de opções pelo nome).
[Parameter("Período da média curta", Min = 2, Max = 200, Step = 1, Group = "Médias")]public int PeriodoCurto = 9;public enum Modo { Tendencia, Reversao }[Parameter("Modo")] public Modo ModoDeOperacao = Modo.Tendencia;[Parameter("Zerar às", Format = ParameterFormat.Time)] public int ZerarAs = 1740;
| Membro | O que faz |
|---|---|
ParameterAttribute(string name) | Marca o parâmetro com o name mostrado na tela. |
string Name | Nome mostrado na tela. |
string? Description | Explicação curta, opcional. |
double Min | Menor valor aceito (ignorado em bool, texto e lista). |
double Max | Maior valor aceito (ignorado em bool, texto e lista). |
double Step | O passo do campo numérico na tela (0,5; 1; 5...). Só ajuda a digitar; não arredonda. |
string? Group | O grupo em que a tela agrupa os parâmetros ("Médias", "Risco"...). |
string[]? Options | Para string: as opções aceitas; o campo vira uma lista (só entra o que está aqui). |
ParameterFormat Format | O formato (hora, cor, ativo, tempo gráfico); Default = o do tipo. |
API · Indicadores
Amplitude média (ATR)
AtrATR de Wilder sobre o true range. O aquecimento é a média simples dos primeiros N true ranges e só então entra a suavização recursiva, como no gráfico da HTS: é assim que o número bate com o das outras plataformas. O primeiro candle (sem anterior) conta com true range = máxima − mínima.
private Atr atr = null!;private Ema media = null!;public override void OnStart() { atr = new Atr(14); media = new Ema(21); }public override void OnBarClose(){ atr.Update(Current); media.Update(Current.Close); // stop de 2 ATRs na entrada if (atr.IsReady && Position.IsFlat && Crossed.Above(Closes, media)) { Buy(); StopLoss(2 * atr.Value); }}
| Membro | O que faz |
|---|---|
Atr(int period) | Cria o ATR com period candles (1 a 500). |
int Period | O período (em candles). |
static double TrueRange(Candle current, Candle? previous) | True range de um candle dado o anterior (ou só a amplitude, sem anterior). |
double Update(Candle candle) | Avança com o candle fechado e devolve o ATR novo (NaN no aquecimento). |
Bandas de Bollinger
BollingerBandas de Bollinger: média simples no meio e bandas a Multiplier desvios-padrão (populacional) de distância. A conta é a do gráfico da HTS: desvio-padrão populacional dos últimos N valores. Value é a média; as bandas ficam em Upper e Lower.
private Bollinger bandas = null!;public override void OnStart() { bandas = new Bollinger(20, 2); }public override void OnBarClose(){ bandas.Update(Current.Close); if (!bandas.IsReady) return; // volta à média: compra abaixo da banda inferior, zera na média if (Position.IsFlat && Current.Close < bandas.Lower) Buy(); else if (Position.IsLong && Current.Close >= bandas.Middle) ClosePosition();}
| Membro | O que faz |
|---|---|
Bollinger(int period, double multiplier = 2) | Cria as bandas com média de period candles e bandas a multiplier desvios-padrão (0,1 a 10). |
int Period | O período (em candles). |
double Multiplier | Quantos desvios-padrão separam cada banda da média. |
double Middle | A média (o mesmo que Value). |
double Upper | A banda superior no candle atual (NaN no aquecimento). |
double Lower | A banda inferior no candle atual (NaN no aquecimento). |
double UpperAgo(int barsAgo) | A banda superior barsAgo candles atrás (0 = agora). |
double LowerAgo(int barsAgo) | A banda inferior barsAgo candles atrás (0 = agora). |
override double Update(double value) | Avança um candle com um valor (o fechamento, outro indicador...) e devolve a média nova (NaN no aquecimento); as bandas avançam junto. |
Saída de um indicador
OutputUma saída secundária de indicador (banda, sinal, histograma), com histórico alinhado aos candles.
private Keltner canal = null!;public override void OnStart() { canal = new Keltner(20, 10, 2); }public override void OnBarClose(){ canal.Update(Current); // a banda superior é uma série: dá para ler o histórico e cruzar Output superior = canal.UpperSeries; if (Position.IsFlat && Crossed.Above(Closes, superior)) Buy();}
| Membro | O que faz |
|---|---|
double this[int barsAgo] | O valor barsAgo candles atrás (0 = agora). Fora do histórico, NaN. |
int Count | Quantos valores já foram calculados (contando os NaN do aquecimento). |
double Value | O valor no candle atual (NaN no aquecimento). |
double Previous | O valor no candle anterior. |
Canal de Keltner
KeltnerCanal de Keltner: EMA do fechamento no meio e bandas a Multiplier·ATR, como o Keltner no gráfico. A média (Value) existe desde o primeiro candle; as bandas ficam NaN enquanto o ATR aquece (N − 1 candles do período do ATR).
private Keltner canal = null!;public override void OnStart() { canal = new Keltner(20, 10, 2); }public override void OnBarClose(){ canal.Update(Current); if (double.IsNaN(canal.Upper)) return; // rompimento da banda de cima, com stop na média if (Position.IsFlat && Current.Close > canal.Upper) { Buy(); StopLoss(Current.Close - canal.Middle); }}
| Membro | O que faz |
|---|---|
Keltner(int period = 20, int atrPeriod = 10, double multiplier = 2) | Cria o canal com EMA de period candles, ATR de atrPeriod candles e bandas a multiplier·ATR (0,1 a 20). |
int Period | O período da EMA do meio (em candles). |
int AtrPeriod | O período do ATR que dá a largura das bandas (em candles). |
double Multiplier | Quantos ATRs separam cada banda da média. |
double Middle | A média (o mesmo que Value). |
double Upper | A banda superior no candle atual (NaN no aquecimento). |
double Lower | A banda inferior no candle atual (NaN no aquecimento). |
double UpperAgo(int barsAgo) | A banda superior barsAgo candles atrás (0 = agora). |
double LowerAgo(int barsAgo) | A banda inferior barsAgo candles atrás (0 = agora). |
Output UpperSeries | A banda superior como série (para Crossed e os utilitários de série). |
Output LowerSeries | A banda inferior como série (para Crossed e os utilitários de série). |
double Update(Candle candle) | Avança com o candle fechado e devolve a média nova; as bandas avançam junto (NaN enquanto o ATR aquece). |
Canal de Donchian
DonchianCanal de Donchian: a maior máxima e a menor mínima dos últimos N candles (contando o atual) e o meio entre as duas, como o Donchian no gráfico. Value é o Middle. NaN até ter N candles.
private Donchian canal = null!;public override void OnStart() { canal = new Donchian(20); }public override void OnBarClose(){ canal.Update(Current); // tartaruga: compra no rompimento da máxima dos 20 candles anteriores, sai no meio do canal if (Position.IsFlat && Current.Close > canal.UpperAgo(1)) Buy(); else if (Position.IsLong && Current.Close < canal.Middle) ClosePosition();}
| Membro | O que faz |
|---|---|
Donchian(int period = 20) | Cria o canal com period candles (1 a 500). |
int Period | O período (em candles). |
double Middle | O meio do canal (o mesmo que Value). |
double Upper | A maior máxima dos últimos N candles (NaN no aquecimento). |
double Lower | A menor mínima dos últimos N candles (NaN no aquecimento). |
double UpperAgo(int barsAgo) | A banda superior barsAgo candles atrás (0 = agora). |
double LowerAgo(int barsAgo) | A banda inferior barsAgo candles atrás (0 = agora). |
ISeries UpperSeries | A máxima do canal como série (para Crossed). |
ISeries LowerSeries | A mínima do canal como série (para Crossed). |
double Update(Candle candle) | Avança com o candle fechado (máxima e mínima) e devolve o meio do canal novo (NaN no aquecimento). |
Envelope de média
EnvelopeEnvelope: média simples com bandas a Percent% acima e abaixo, como o Envelope no gráfico. Value é a média. NaN até ter N valores.
private Envelope envelope = null!;public override void OnStart() { envelope = new Envelope(20, 0.5); }public override void OnBarClose(){ envelope.Update(Current.Close); if (!envelope.IsReady) return; // esticou 0,5% acima da média: vende buscando a volta if (Position.IsFlat && Current.Close > envelope.Upper) Sell(); else if (Position.IsShort && Current.Close <= envelope.Middle) ClosePosition();}
| Membro | O que faz |
|---|---|
Envelope(int period = 20, double percent = 2) | Cria o envelope com média de period candles e bandas a percent% da média (acima de 0 até 100). |
int Period | O período da média (em candles). |
double Percent | A distância de cada banda à média, em % da média. |
double Middle | A média (o mesmo que Value). |
double Upper | A banda superior no candle atual (NaN no aquecimento). |
double Lower | A banda inferior no candle atual (NaN no aquecimento). |
double UpperAgo(int barsAgo) | A banda superior barsAgo candles atrás (0 = agora). |
double LowerAgo(int barsAgo) | A banda inferior barsAgo candles atrás (0 = agora). |
Output UpperSeries | A banda superior como série (para Crossed e os utilitários de série). |
Output LowerSeries | A banda inferior como série (para Crossed e os utilitários de série). |
override double Update(double value) | Avança um candle com um valor (o fechamento, outro indicador...) e devolve a média nova (NaN no aquecimento); as bandas avançam junto. |
Cruzamento
CrossedCruzamentos entre duas séries (indicador, Series, Closes...), ou entre uma série e um nível fixo. Um cruzamento só existe quando os dois valores (de agora e do candle anterior) são números: no aquecimento a resposta é sempre false.
private readonly Ema _rapida = new(9);private readonly Ema _lenta = new(21);public override void OnBarClose(){ _rapida.Update(Current); _lenta.Update(Current); if (Position.IsFlat && Crossed.Above(_rapida, _lenta)) Buy(1); else if (Position.IsLong && Crossed.Below(_rapida, _lenta)) ClosePosition();}
| Membro | O que faz |
|---|---|
static bool Above(ISeries a, ISeries b) | a estava abaixo ou igual a b e agora está acima. |
static bool Below(ISeries a, ISeries b) | a estava acima ou igual a b e agora está abaixo. |
static bool Above(ISeries a, double level) | A série estava abaixo ou igual ao nível e agora está acima. |
static bool Below(ISeries a, double level) | A série estava acima ou igual ao nível e agora está abaixo. |
static bool Above(double aBefore, double aNow, double bBefore, double bNow) | Cruzou para cima com valores avulsos: a estava abaixo ou igual a b antes e agora está acima. |
static bool Below(double aBefore, double aNow, double bBefore, double bNow) | Cruzou para baixo com valores avulsos: a estava acima ou igual a b antes e agora está abaixo. |
Heikin-Ashi
HeikinAshiHeikin-Ashi: os candles "médios", um por candle de verdade. Fechamento = (A + M + m + F) / 4; abertura = média da abertura e do fechamento do Heikin-Ashi anterior (o primeiro usa (A + F) / 2 do candle real); máxima e mínima incluem a abertura e o fechamento novos. Value é o fechamento HA; o candle inteiro está em Current e o histórico em CandleAgo. O tempo e o volume são os do candle real.
private HeikinAshi ha = null!;public override void OnStart() { ha = new HeikinAshi(); }public override void OnBarClose(){ ha.Update(Current); // primeiro candle Heikin-Ashi de alta depois de um de baixa: compra if (ha.CandleAgo(1) is Candle anterior && ha.IsBullish && anterior.IsBearish && Position.IsFlat) Buy(); else if (Position.IsLong && !ha.IsBullish) ClosePosition();}
| Membro | O que faz |
|---|---|
Candle? Current | O candle Heikin-Ashi de agora; null antes do primeiro. |
Candle? CandleAgo(int barsAgo) | O candle Heikin-Ashi barsAgo candles antes (0 = agora); null fora do histórico. |
IReadOnlyList<Candle> Candles | Todos os candles Heikin-Ashi até agora (para passar a outro indicador, por exemplo). |
bool IsBullish | O candle de agora é de alta (fechamento HA acima da abertura HA). |
double Update(Candle candle) | Avança com o candle real fechado, monta o candle Heikin-Ashi correspondente e devolve o fechamento HA. |
Tijolo do Renko
BrickUm tijolo do Renko: de onde saiu, até onde foi, o lado e o candle (tempo) em que fechou.
private Renko renko = null!;public override void OnStart() { renko = new Renko(100); }public override void OnBarClose(){ renko.Update(Current); // o último tijolo fechado: lado e preços if (renko.NewBricks > 0 && renko.Last is Brick tijolo) Log($"Tijolo {tijolo.Side}: {tijolo.Open} a {tijolo.Close}");}
| Membro | O que faz |
|---|---|
double Open | O preço em que o tijolo começa. |
double Close | O preço em que o tijolo termina. |
Side Side | O lado do tijolo: Long de alta, Short de baixa. |
long Time | O início, em segundos Unix, do candle em que o tijolo fechou. |
Renko
RenkoRenko: tijolos de tamanho fixo em pontos sobre o FECHAMENTO dos candles. Um tijolo novo no mesmo sentido precisa andar Size além do topo (ou fundo) do último; a reversão precisa de 2 × tamanho (a regra clássica: o tijolo contrário começa do outro lado do último). Um candle pode fechar vários tijolos (ou nenhum). Value é o fechamento do último tijolo, repetido nos candles sem tijolo novo; NewBricks diz quantos fecharam neste candle.
private Renko renko = null!;public override void OnStart() { renko = new Renko(100); }public override void OnBarClose(){ renko.Update(Current); // virada do Renko de 100 pontos: segue o lado do tijolo novo if (renko.FlippedNow && renko.Direction == Side.Long) { ClosePosition(); Buy(); } else if (renko.FlippedNow && renko.Direction == Side.Short) { ClosePosition(); Sell(); }}
| Membro | O que faz |
|---|---|
Renko(double size) | Cria o Renko com tijolos de size pontos (positivo). |
double Size | O tamanho do tijolo, em pontos. |
IReadOnlyList<Brick> Bricks | Os tijolos fechados até agora, do mais antigo ao mais novo. |
Brick? Last | O último tijolo; null antes do primeiro. |
int NewBricks | Quantos tijolos fecharam no último candle. |
Side Direction | O lado do último tijolo (Flat antes do primeiro). |
bool FlippedNow | Virou de lado neste candle (o primeiro tijolo do candle é contrário ao último de antes). |
double Update(Candle candle) | Avança com o candle fechado (o fechamento e o tempo) e devolve o fechamento do último tijolo (NaN antes do primeiro). |
double Update(double price, long time = 0) | Avança com um preço price (um por candle) e o tempo time gravado nos tijolos que fecharem; devolve o fechamento do último tijolo (NaN antes do primeiro). |
Máxima de N candles
HighestA maior máxima dos últimos N candles (contando o atual). NaN até ter N candles.
private Highest maxima = null!;public override void OnStart() { maxima = new Highest(20); }public override void OnBarClose(){ maxima.Update(Current); // rompimento: fechou acima da maior máxima dos 20 candles anteriores if (Position.IsFlat && Current.Close > maxima[1]) Buy();}
| Membro | O que faz |
|---|---|
Highest(int period) | Cria o indicador com period candles (1 a 500). |
int Period | O período (em candles). |
double Update(Candle candle) | Avança com o candle fechado (a máxima) e devolve a maior máxima nova (NaN no aquecimento). |
Mínima de N candles
LowestA menor mínima dos últimos N candles (contando o atual). NaN até ter N candles.
private Lowest minima = null!;public override void OnStart() { minima = new Lowest(10); }public override void OnBarClose(){ minima.Update(Current); // saída da compra: fechou abaixo da menor mínima dos 10 candles anteriores if (Position.IsLong && Current.Close < minima[1]) ClosePosition();}
| Membro | O que faz |
|---|---|
Lowest(int period) | Cria o indicador com period candles (1 a 500). |
int Period | O período (em candles). |
double Update(Candle candle) | Avança com o candle fechado (a mínima) e devolve a menor mínima nova (NaN no aquecimento). |
Ichimoku
IchimokuIchimoku Kinko Hyo: Tenkan (meio da faixa de 9), Kijun (meio da faixa de 26), Senkou A (média das duas) e Senkou B (meio da faixa de 52), as duas últimas desenhadas 26 candles À FRENTE, e Chikou (o fechamento de agora, desenhado 26 candles ATRÁS). Mesma conta do Ichimoku no gráfico; o deslocamento é o período do Kijun, como no sistema original. Para o robô, o que importa é a nuvem SOB O CANDLE ATUAL: SenkouA e SenkouB são os valores calculados 26 candles atrás, que é onde o gráfico os desenha hoje ("preço acima da nuvem" = Close > Math.Max(SenkouA, SenkouB)). SenkouAFuture e SenkouBFuture são os calculados agora, a nuvem daqui a 26 candles. Chikou é o fechamento de agora e CloseAtChikou o fechamento de 26 candles atrás, que é com quem o Chikou se compara no gráfico. Value é o Tenkan.
private Ichimoku ichi = null!;public override void OnStart() { ichi = new Ichimoku(9, 26, 52); }public override void OnBarClose(){ ichi.Update(Current); // Tenkan cruzou o Kijun para cima com o preço acima da nuvem if (Position.IsFlat && Current.Close > ichi.CloudTop && Crossed.Above(ichi, ichi.KijunSeries)) Buy(1);}
| Membro | O que faz |
|---|---|
Ichimoku(int tenkan = 9, int kijun = 26, int senkou = 52) | Cria o Ichimoku com as faixas do Tenkan (tenkan), do Kijun (kijun, também o deslocamento) e do Senkou B (senkou), em candles. |
int TenkanPeriod | A faixa do Tenkan, em candles. |
int KijunPeriod | A faixa do Kijun, em candles (também o deslocamento). |
int SenkouPeriod | A faixa do Senkou B, em candles. |
int Displacement | Quantos candles a nuvem é jogada à frente e o Chikou para trás (= período do Kijun). |
double Tenkan | O Tenkan (o mesmo que Value). |
double Kijun | O Kijun (meio da faixa de KijunPeriod candles). |
double SenkouA | Senkou A sob o candle atual (calculado Displacement candles atrás). |
double SenkouB | Senkou B sob o candle atual. |
double SenkouAFuture | Senkou A calculado agora (a nuvem daqui a Displacement candles). |
double SenkouBFuture | Senkou B calculado agora (a nuvem daqui a Displacement candles). |
double Chikou | O fechamento de agora (o gráfico o desenha Displacement candles atrás). |
double CloseAtChikou | O fechamento de Displacement candles atrás: o preço sob o Chikou. |
double CloudTop | O topo da nuvem sob o candle atual. |
double CloudBottom | A base da nuvem sob o candle atual. |
double TenkanAgo(int barsAgo) | O Tenkan barsAgo candles atrás (0 = agora). |
double KijunAgo(int barsAgo) | O Kijun barsAgo candles atrás (0 = agora). |
double SenkouAAgo(int barsAgo) | O Senkou A sob o candle de barsAgo candles atrás (0 = sob o atual, como SenkouA). |
double SenkouBAgo(int barsAgo) | O Senkou B sob o candle de barsAgo candles atrás (0 = sob o atual, como SenkouB). |
Output KijunSeries | O Kijun como série (para Crossed e os utilitários de série). |
Output SenkouAFutureSeries | O Senkou A como série, alinhado ao candle em que foi CALCULADO (sem o deslocamento à frente). |
Output SenkouBFutureSeries | O Senkou B como série, alinhado ao candle em que foi CALCULADO (sem o deslocamento à frente). |
Output CloseSeries | Os fechamentos como série (a base do Chikou). |
double Update(Candle candle) | Recebe o candle fechado e devolve o Tenkan novo (NaN no aquecimento); Kijun, Senkou A/B e Chikou são atualizados junto. |
Indicador (base)
IndicatorBase dos indicadores: uma série que avança um valor por candle e guarda o histórico, para o robô comparar o valor de agora com o de candles atrás (media[1] é o do candle anterior). Durante o aquecimento o valor é NaN, exatamente como no gráfico da HTS. Todo indicador é uma ISeries: os utilitários de série (Average(n), Highest(n), Rising(n)...) valem para ele.
private readonly Ema _media = new(21);public override void OnBarClose(){ _media.Update(Current); // média pronta e subindo, preço acima dela: compra if (_media.IsReady && _media.Value > _media[1] && Current.Close > _media.Value && Position.IsFlat) Buy(1);}
| Membro | O que faz |
|---|---|
double Value | O valor no candle atual (NaN no aquecimento). |
double Previous | O valor no candle anterior. |
double this[int barsAgo] | O valor barsAgo candles antes do atual (0 = atual). Fora do histórico, NaN. |
int Count | Quantos valores já foram calculados (contando os NaN do aquecimento). |
bool IsReady | O indicador já saiu do aquecimento (o valor atual é um número). |
Indicador de um valor (base)
ValueIndicatorIndicador alimentado por um valor por candle (por padrão, o fechamento).
private readonly Sma _mediaDoMeio = new(20);public override void OnBarClose(){ // Update aceita o candle (usa o fechamento) ou qualquer número _mediaDoMeio.Update((Current.High + Current.Low) / 2); if (_mediaDoMeio.IsReady) Plot("Média do meio", _mediaDoMeio.Value);}
| Membro | O que faz |
|---|---|
abstract double Update(double value) | Avança um candle com um valor qualquer (fechamento, outro indicador, etc.). |
double Update(Candle candle) | Avança um candle usando o fechamento. |
Média exponencial
EmaMédia móvel exponencial com k = 2 / (N + 1). Semeia com o primeiro valor válido e devolve esse valor já no primeiro candle, como a EMA do gráfico da HTS: os primeiros valores carregam o peso da semente. Valor não numérico não avança a média (devolve a anterior).
private Ema rapida = null!;private Ema lenta = null!;public override void OnStart() { rapida = new Ema(9); lenta = new Ema(21); }public override void OnBarClose(){ rapida.Update(Current.Close); lenta.Update(Current.Close); // cruzamento clássico das médias 9 e 21 if (Crossed.Above(rapida, lenta)) Buy(); else if (Crossed.Below(rapida, lenta)) Sell();}
| Membro | O que faz |
|---|---|
Ema(int period) | Cria a média exponencial com period candles (1 a 500). |
int Period | O período (em candles). |
override double Update(double value) | Avança um candle com um valor (o fechamento, outro indicador...) e devolve a média nova; valor que não é número devolve a anterior. |
Média móvel simples
SmaMédia móvel simples: a média aritmética dos últimos N valores. NaN até ter N valores, e NaN se algum valor da janela não for número (mesma regra do gráfico da HTS).
private Sma media = null!;public override void OnStart() { media = new Sma(20); }public override void OnBarClose(){ media.Update(Current.Close); // só desenha a média quando o fechamento está acima dela if (media.IsReady && Current.Close > media.Value) Plot("Média", media.Value);}
| Membro | O que faz |
|---|---|
Sma(int period) | Cria a média simples com period candles (1 a 500). |
int Period | O período (em candles). |
override double Update(double value) | Avança um candle com um valor (o fechamento, outro indicador...) e devolve a média nova (NaN no aquecimento). |
Média ponderada
WmaMédia móvel ponderada (WMA): o candle mais recente pesa N, o anterior N − 1, e assim por diante. NaN até ter N valores e NaN se algum valor da janela não é número (mesma conta do WMA no gráfico).
private Wma media = null!;public override void OnStart() { media = new Wma(21); }public override void OnBarClose(){ media.Update(Current.Close); // compra quando o fechamento cruza a média para cima if (Position.IsFlat && Crossed.Above(Closes, media)) Buy();}
| Membro | O que faz |
|---|---|
Wma(int period) | Cria a WMA com period candles (1 a 500). |
int Period | O período (em candles). |
override double Update(double value) | Avança um candle com um valor (o fechamento, outro indicador...) e devolve a WMA nova (NaN no aquecimento). |
Média de Hull
HmaMédia de Hull (HMA): WMA(√N) de [2·WMA(N/2) − WMA(N)], a conta do HMA no gráfico (N/2 arredondado para baixo, √N arredondado para o inteiro mais próximo). Aquecimento: N + √N − 2 candles de NaN.
private Hma hull = null!;public override void OnStart() { hull = new Hma(16); }public override void OnBarClose(){ hull.Update(Current.Close); if (!hull.IsReady) return; // verde subindo, vermelha caindo Plot("Hull", hull.Value, hull.Value > hull.Previous ? "#22c55e" : "#ef4444");}
| Membro | O que faz |
|---|---|
Hma(int period) | Cria a média de Hull com period candles (1 a 500). |
int Period | O período (em candles). |
override double Update(double value) | Avança um candle com um valor (o fechamento, outro indicador...) e devolve a HMA nova (NaN no aquecimento). |
Média de Wilder
RmaMédia de Wilder (RMA/SMMA, a que roda por dentro do RSI e do ATR): semeia com a média simples dos primeiros N valores e depois avança por (anterior·(N − 1) + valor)/N, como o SMMA no gráfico. NaN nos N − 1 primeiros candles. Valor não numérico devolve a média anterior sem avançar.
private Rma amplitude = null!;public override void OnStart() { amplitude = new Rma(14); }public override void OnBarClose(){ // média de Wilder da amplitude dos candles amplitude.Update(Current.High - Current.Low); if (amplitude.IsReady && Current.Range > 2 * amplitude.Value) Log("Candle esticado: o dobro da amplitude média");}
| Membro | O que faz |
|---|---|
Rma(int period) | Cria a média de Wilder com period candles (1 a 500). |
int Period | O período (em candles). |
override double Update(double value) | Avança um candle com um valor (o fechamento, outro indicador...) e devolve a média nova (NaN no aquecimento). |
Média ponderada por volume
VwmaMédia ponderada por volume (VWMA): Σ(fechamento·volume)/Σ(volume) nos últimos N candles, como o VWMA no gráfico. Precisa do candle (volume), por isso só tem Update. NaN até ter N candles e quando o volume da janela é zero.
private Vwma porVolume = null!;private Sma simples = null!;public override void OnStart() { porVolume = new Vwma(20); simples = new Sma(20); }public override void OnBarClose(){ porVolume.Update(Current); simples.Update(Current.Close); // VWMA acima da média simples: o volume está do lado comprador if (porVolume.IsReady && simples.IsReady && porVolume.Value > simples.Value) Plot("VWMA", porVolume.Value);}
| Membro | O que faz |
|---|---|
Vwma(int period) | Cria a VWMA com period candles (1 a 500). |
int Period | O período (em candles). |
double Update(Candle candle) | Avança com o candle fechado (fechamento e volume) e devolve a VWMA nova (NaN no aquecimento). |
Média de Arnaud Legoux (ALMA)
AlmaALMA (Arnaud Legoux): pesos em curva de sino com o centro em offset·(N − 1) e largura N/sigma, como o ALMA no gráfico. NaN até ter N valores.
private Alma alma = null!;public override void OnStart() { alma = new Alma(21, 0.85, 6); }public override void OnBarClose(){ alma.Update(Current.Close); // zera a compra quando o fechamento perde a ALMA if (Position.IsLong && Crossed.Below(Closes, alma)) ClosePosition();}
| Membro | O que faz |
|---|---|
Alma(int period, double offset = 0.85, double sigma = 6) | Cria o ALMA com period candles, o centro dos pesos em offset (0 a 1; perto de 1 favorece os candles recentes) e a largura da curva dada por sigma (maior = curva mais estreita). |
int Period | O período (em candles). |
double Offset | Onde fica o centro dos pesos na janela, de 0 (o candle mais antigo) a 1 (o mais recente). |
double Sigma | O sigma da curva de pesos (a largura é N/sigma; maior = pesos mais concentrados no centro). Mínimo 0,1. |
override double Update(double value) | Avança um candle com um valor (o fechamento, outro indicador...) e devolve o ALMA novo (NaN no aquecimento). |
Média adaptativa de Kaufman (KAMA)
KamaKAMA (Kaufman): a velocidade da suavização vem da eficiência do movimento (quanto o preço andou em linha reta contra o caminho total nos últimos N candles), entre as EMAs de fastPeriod e slowPeriod. Mesma conta do KAMA no gráfico: NaN nos N primeiros candles (a semente é o fechamento do N-ésimo) e o primeiro valor sai no candle N + 1.
private Kama kama = null!;public override void OnStart() { kama = new Kama(10, 2, 30); }public override void OnBarClose(){ kama.Update(Current.Close); if (!kama.IsReady) return; // KAMA parada = mercado lateral; só compra com ela subindo if (Position.IsFlat && kama.Value > kama.Previous && Current.Close > kama.Value) Buy();}
| Membro | O que faz |
|---|---|
Kama(int period, int fastPeriod = 2, int slowPeriod = 30) | Cria o KAMA com eficiência medida em period candles, variando entre a EMA de fastPeriod (movimento eficiente) e a de slowPeriod (mercado lateral). |
int Period | O período da medida de eficiência (em candles). |
int Fast | O período da EMA rápida, usada quando o preço anda em linha reta. |
int Slow | O período da EMA lenta, usada quando o preço anda de lado. |
override double Update(double value) | Avança um candle com um valor (o fechamento, outro indicador...) e devolve o KAMA novo (NaN no aquecimento). |
Média exponencial dupla
DemaDEMA: 2·EMA − EMA(EMA), como o DEMA no gráfico. Tem valor desde o primeiro candle (as EMAs semeiam com o primeiro valor) e converge ao longo dos primeiros candles.
private Dema rapida = null!;private Dema lenta = null!;public override void OnStart() { rapida = new Dema(9); lenta = new Dema(21); }public override void OnBarClose(){ rapida.Update(Current.Close); lenta.Update(Current.Close); // cruzamento de duas DEMAs if (Crossed.Above(rapida, lenta)) Buy(); else if (Crossed.Below(rapida, lenta)) Sell();}
| Membro | O que faz |
|---|---|
Dema(int period) | Cria a DEMA com period candles (1 a 500). |
int Period | O período (em candles). |
override double Update(double value) | Avança um candle com um valor (o fechamento, outro indicador...) e devolve a DEMA nova; valor que não é número devolve a anterior. |
Média exponencial tripla
TemaTEMA: 3·EMA − 3·EMA(EMA) + EMA(EMA(EMA)), como o TEMA no gráfico. Valor desde o primeiro candle.
private Tema tema = null!;public override void OnStart() { tema = new Tema(20); }public override void OnBarClose(){ tema.Update(Current.Close); Plot("TEMA", tema.Value); // vende quando o fechamento perde a TEMA if (Position.IsFlat && Crossed.Below(Closes, tema)) Sell();}
| Membro | O que faz |
|---|---|
Tema(int period) | Cria a TEMA com period candles (1 a 500). |
int Period | O período (em candles). |
override double Update(double value) | Avança um candle com um valor (o fechamento, outro indicador...) e devolve a TEMA nova; valor que não é número devolve a anterior. |
TRIX
TrixTRIX: variação percentual (em pontos-base, ×10 000) da EMA tripla de um candle para o outro, como o TRIX no gráfico. NaN só no primeiro candle.
private Trix trix = null!;public override void OnStart() { trix = new Trix(15); }public override void OnBarClose(){ trix.Update(Current.Close); // TRIX cruzando o zero para cima: a tendência virou de alta if (Position.IsFlat && Crossed.Above(trix, 0)) Buy(); else if (Position.IsLong && Crossed.Below(trix, 0)) ClosePosition();}
| Membro | O que faz |
|---|---|
Trix(int period) | Cria o TRIX com period candles em cada uma das três EMAs (1 a 500). |
int Period | O período de cada EMA (em candles). |
override double Update(double value) | Avança um candle com um valor (o fechamento, outro indicador...) e devolve o TRIX novo (NaN no primeiro candle e quando o valor não é número). |
Média T3 de Tillson
T3T3 (Tillson): seis EMAs encadeadas combinadas pelo fator de volume factor, como o T3 no gráfico. Valor desde o primeiro candle; converge ao longo do aquecimento.
private T3 t3 = null!;public override void OnStart() { t3 = new T3(8, 0.7); }public override void OnBarClose(){ t3.Update(Current.Close); // compra com o fechamento acima da T3 e a T3 subindo if (Position.IsFlat && Current.Close > t3.Value && t3.Value > t3.Previous) Buy(); Plot("T3", t3.Value);}
| Membro | O que faz |
|---|---|
T3(int period, double factor = 0.7) | Cria o T3 com period candles em cada EMA e o fator de volume factor (0 a 1; com 0 o T3 vira a EMA da EMA da EMA). |
int Period | O período de cada EMA (em candles). |
double Factor | O fator de volume (0 a 1) que combina as EMAs encadeadas. |
override double Update(double value) | Avança um candle com um valor (o fechamento, outro indicador...) e devolve o T3 novo; valor que não é número devolve o anterior. |
Série deslocada
ShiftedUma série vista com deslocamento: Shifted(media, 5)[0] é o valor que media tinha 5 candles atrás (a média "deslocada para a frente" do gráfico, o offset do Pine). Não copia nada: lê a série original na hora, então vale para qualquer indicador ou Series. Deslocamento negativo não existe (seria ler o futuro).
private Sma media = null!;private Shifted deslocada = null!;public override void OnStart() { media = new Sma(20); deslocada = new Shifted(media, 3); }public override void OnBarClose(){ media.Update(Current.Close); // compra quando o fechamento cruza a média deslocada 3 candles if (Position.IsFlat && Crossed.Above(Closes, deslocada)) Buy();}
| Membro | O que faz |
|---|---|
Shifted(ISeries source, int offset) | Lê source com offset candles de atraso (0 a 5000). |
int Shift | O deslocamento (em candles). |
double this[int barsAgo] | O valor da série deslocada barsAgo candles atrás (0 = agora), ou seja, o da fonte barsAgo + Shift candles atrás. |
int Count | Quantos valores a série deslocada tem (os da fonte menos o deslocamento). |
double Value | O valor deslocado no candle atual. |
double Previous | O valor deslocado no candle anterior. |
Índice de fluxo de dinheiro (MFI)
MfiMFI (Money Flow Index): o RSI com volume. Fluxo = preço típico × volume; soma dos fluxos dos candles em que o típico subiu contra os em que caiu, nos últimos N candles, de 0 a 100. Mesma conta do MFI no gráfico: a comparação precisa do candle anterior, então o primeiro valor sai no candle N + 1 (N candles de NaN).
private Mfi mfi = null!;public override void OnStart() { mfi = new Mfi(14); }public override void OnBarClose(){ mfi.Update(Current); // pouco dinheiro entrando (abaixo de 20): compra; excesso (acima de 80): zera if (Position.IsFlat && mfi.Value < 20) Buy(1); else if (Position.IsLong && mfi.Value > 80) ClosePosition();}
| Membro | O que faz |
|---|---|
Mfi(int period = 14) | Cria o MFI com period candles (padrão 14). |
int Period | O período (em candles). |
double Update(Candle candle) | Recebe o candle fechado (usa máxima, mínima, fechamento e volume) e devolve o MFI novo, de 0 a 100 (NaN no aquecimento). |
Oscilador de momento de Chande (CMO)
CmoCMO (Chande): (Σ altas − Σ baixas)/(Σ altas + Σ baixas) × 100 nas últimas N variações, de −100 a 100, sem alisamento, como o CMO no gráfico. Primeiro valor no candle N + 1.
private Cmo cmo = null!;public override void OnStart() { cmo = new Cmo(14); }public override void OnBarClose(){ cmo.Update(Current.Close); // abaixo de −50 é sobrevenda; acima de +50, sobrecompra if (Position.IsFlat && cmo.Value < -50) Buy(1); else if (Position.IsLong && cmo.Value > 50) ClosePosition();}
| Membro | O que faz |
|---|---|
Cmo(int period = 14) | Cria o CMO com period variações (padrão 14). |
int Period | O período (em candles). |
override double Update(double value) | Recebe o próximo valor (normalmente o fechamento) e devolve o CMO novo, de −100 a 100 (NaN no aquecimento). |
Taxa de variação (ROC)
RocROC: variação percentual entre o valor de agora e o de N candles atrás, como o ROC no gráfico. NaN nos N primeiros candles e quando o valor de referência é zero.
private Roc roc = null!;public override void OnStart() { roc = new Roc(12); }public override void OnBarClose(){ roc.Update(Current.Close); Plot("ROC %", roc.Value, PlotStyle.Histogram); // a variação em 12 candles virou positiva: compra if (Position.IsFlat && Crossed.Above(roc, 0)) Buy(1);}
| Membro | O que faz |
|---|---|
Roc(int period = 12) | Cria o ROC comparando com o valor de period candles atrás (padrão 12). |
int Period | O período (em candles). |
override double Update(double value) | Recebe o próximo valor (normalmente o fechamento) e devolve o ROC novo, em % (NaN no aquecimento). |
Momento
MomentumMomentum: o valor de agora menos o de N candles atrás, em pontos, como o Momentum no gráfico. NaN nos N primeiros candles.
private Momentum mom = null!;public override void OnStart() { mom = new Momentum(10); }public override void OnBarClose(){ mom.Update(Current.Close); // momento cruzou o zero: compra para cima, zera para baixo if (Position.IsFlat && Crossed.Above(mom, 0)) Buy(1); else if (Position.IsLong && Crossed.Below(mom, 0)) ClosePosition();}
| Membro | O que faz |
|---|---|
Momentum(int period = 10) | Cria o Momentum comparando com o valor de period candles atrás (padrão 10). |
int Period | O período (em candles). |
override double Update(double value) | Recebe o próximo valor (normalmente o fechamento) e devolve o Momentum novo, em pontos (NaN no aquecimento). |
Índice de força verdadeira (TSI)
TsiTSI (True Strength Index): a variação do preço alisada por duas EMAs (longa e depois curta), dividida pelo valor absoluto da variação alisado do mesmo jeito, × 100. Mesma conta do TSI no gráfico: as EMAs semeiam com a primeira variação, então o valor existe desde o segundo candle e converge.
private Tsi tsi = null!;public override void OnStart() { tsi = new Tsi(25, 13); }public override void OnBarClose(){ tsi.Update(Current.Close); Plot("TSI", tsi.Value); // TSI cruzou o zero: compra para cima, zera para baixo if (Position.IsFlat && Crossed.Above(tsi, 0)) Buy(1); else if (Position.IsLong && Crossed.Below(tsi, 0)) ClosePosition();}
| Membro | O que faz |
|---|---|
Tsi(int longPeriod = 25, int shortPeriod = 13) | Cria o TSI com a EMA longa de longPeriod e a curta de shortPeriod candles. |
int LongPeriod | O período da primeira EMA (a longa), em candles. |
int ShortPeriod | O período da segunda EMA (a curta), em candles. |
override double Update(double value) | Recebe o próximo valor (normalmente o fechamento) e devolve o TSI novo, de −100 a 100 (NaN no primeiro candle). |
Oscilador final
UltimateOscillatorUltimate Oscillator (Larry Williams): pressão compradora (fechamento − mínimo entre a mínima e o fechamento anterior) sobre a amplitude verdadeira, em três janelas combinadas com pesos 4, 2 e 1, de 0 a 100. Mesma conta do Ultimate Oscillator no gráfico. NaN até ter Long candles.
private UltimateOscillator uo = null!;public override void OnStart() { uo = new UltimateOscillator(7, 14, 28); }public override void OnBarClose(){ uo.Update(Current); // abaixo de 30 é sobrevenda; acima de 70, sobrecompra if (Position.IsFlat && uo.Value < 30) Buy(1); else if (Position.IsLong && uo.Value > 70) ClosePosition();}
| Membro | O que faz |
|---|---|
UltimateOscillator(int shortPeriod = 7, int mediumPeriod = 14, int longPeriod = 28) | Cria o oscilador com as janelas curta (shortPeriod), média (mediumPeriod) e longa (longPeriod), em candles. |
int Short | A janela curta (peso 4), em candles. |
int Medium | A janela média (peso 2), em candles. |
int Long | A janela longa (peso 1), em candles. |
double Update(Candle candle) | Recebe o candle fechado e devolve o Ultimate Oscillator novo, de 0 a 100 (NaN no aquecimento). |
Níveis de pivô
PivotLevelsOs sete níveis de um pivô.
Bar? ontem = PreviousDay;if (ontem is not null){ PivotLevels p = Pivots.Classic(ontem.Value); // desenha o pivô e a primeira resistência e suporte do dia Plot("PP", p.PP); Plot("R1", p.R1); Plot("S1", p.S1);}
| Membro | O que faz |
|---|---|
double PP | O pivô central. |
double R1 | A primeira resistência (a mais perto, acima). |
double R2 | A segunda resistência. |
double R3 | A terceira resistência (a mais longe, acima). |
double S1 | O primeiro suporte (o mais perto, abaixo). |
double S2 | O segundo suporte. |
double S3 | O terceiro suporte (o mais longe, abaixo). |
Pivôs
PivotsPivôs calculados da máxima, mínima e fechamento do período ANTERIOR (o dia de ontem, a semana passada), com as mesmas fórmulas do Pivot do gráfico. Você passa os números (normalmente de PreviousDay, ou Aggregates.Previous(Candles, Candles.Count - 1, Period.Day)).
Bar? ontem = PreviousDay;if (ontem is not null){ PivotLevels p = Pivots.Classic(ontem.Value); // rompeu a R1 de baixo para cima: compra mirando a R2, stop no pivô if (Position.IsFlat && Closes[1] <= p.R1 && Current.Close > p.R1) { Buy(1); TakeProfitAt(p.R2); StopLossAt(p.PP); }}
| Membro | O que faz |
|---|---|
static PivotLevels Classic(double high, double low, double close) | Clássico: PP = (H + L + C)/3; R1 = 2PP − L; R2 = PP + (H − L); R3 = H + 2(PP − L); e os suportes espelhados. |
static PivotLevels Fibonacci(double high, double low, double close) | Fibonacci: PP = (H + L + C)/3 e níveis a 38,2%, 61,8% e 100% da amplitude. |
static PivotLevels Camarilla(double high, double low, double close) | Camarilla: níveis apertados em volta do FECHAMENTO (C ± amplitude × 1,1/12, /6 e /4); PP = (H + L + C)/3. |
static PivotLevels Classic(Bar previousPeriod) | Pivô clássico a partir da máxima, mínima e fechamento de previousPeriod. |
static PivotLevels Fibonacci(Bar previousPeriod) | Pivô Fibonacci a partir da máxima, mínima e fechamento de previousPeriod. |
static PivotLevels Camarilla(Bar previousPeriod) | Pivô Camarilla a partir da máxima, mínima e fechamento de previousPeriod. |
Topos e fundos
SwingsTopos e fundos confirmados: o candle cuja máxima supera estritamente a dos Left candles antes e dos Right candles depois é um topo (idem, espelhado, para o fundo), a regra dos fractais do gráfico com lados independentes. A confirmação chega com Right candles de atraso: em HighConfirmedNow o topo é o candle de Right candles atrás, e LastHigh passa a valer o preço dele. Highs e Lows são séries alinhadas ao candle da CONFIRMAÇÃO (o preço do extremo, ou NaN).
private Swings swings = null!;public override void OnStart() { swings = new Swings(2, 2); }public override void OnBarClose(){ swings.Update(Current); // confirmou um fundo mais alto que o anterior: compra com stop abaixo dele if (Position.IsFlat && swings.LowConfirmedNow && swings.LastLow > swings.PreviousLow) { Buy(1); StopLossAt(swings.LastLow - 5); }}
| Membro | O que faz |
|---|---|
Swings(int left = 2, int right = 2) | Cria o detector com left candles de comparação antes e right depois do extremo (1 a 500 cada). |
int Left | Quantos candles antes do extremo ele precisa superar. |
int Right | Quantos candles depois do extremo ele precisa superar (é o atraso da confirmação). |
double LastHigh | O preço do último topo confirmado (NaN se ainda não houve). |
double LastLow | O preço do último fundo confirmado. |
double PreviousHigh | O topo confirmado antes do último (para "topo mais alto que o anterior"). |
double PreviousLow | O fundo confirmado antes do último (para "fundo mais baixo que o anterior"). |
bool HighConfirmedNow | Neste candle confirmou-se um topo (o de Right candles atrás). |
bool LowConfirmedNow | Neste candle confirmou-se um fundo (o de Right candles atrás). |
int BarsSinceHigh | Há quantos candles está o último topo (0 = o atual; −1 se não houve). |
int BarsSinceLow | Há quantos candles está o último fundo (0 = o atual; −1 se não houve). |
ISeries Highs | Série dos topos no candle em que foram confirmados (preço ou NaN). |
ISeries Lows | Série dos fundos no candle em que foram confirmados (preço ou NaN). |
void Update(Candle candle) | Recebe o candle fechado e verifica se ele confirma um topo ou fundo de Right candles atrás. |
Regressão linear
LinearRegressionRegressão linear dos últimos N valores: Value é o valor da reta no candle atual (a LSMA e o canal de regressão do gráfico), Slope é a taxa por candle e R2 o quanto a reta explica, de 0 a 1. Forecast estende a reta para a frente (com 1 é a EPMA). NaN até ter N valores.
private LinearRegression reg = null!;public override void OnStart() { reg = new LinearRegression(20); }public override void OnBarClose(){ reg.Update(Current.Close); Plot("LSMA", reg.Value); // reta subindo e bem ajustada: tendência de alta limpa if (Position.IsFlat && reg.Slope > 0 && reg.R2 > 0.7) Buy(1);}
| Membro | O que faz |
|---|---|
LinearRegression(int period = 20) | Cria a regressão com os últimos period valores (padrão 20). |
int Period | O período (em candles). |
double Slope | A inclinação da reta: quanto ela anda por candle. |
double Intercept | O valor da reta no candle mais antigo da janela (x = 0). |
double R2 | O R² da reta, de 0 a 1 (quanto ela explica dos valores). |
double SlopeAgo(int barsAgo) | A inclinação barsAgo candles atrás (0 = agora). |
double R2Ago(int barsAgo) | O R² barsAgo candles atrás (0 = agora). |
Output SlopeSeries | A inclinação como série (para Crossed e os utilitários de série). |
Output R2Series | O R² como série (para Crossed e os utilitários de série). |
double Forecast(int barsAhead) | O valor da reta barsAhead candles depois do atual (0 = o próprio Value). |
override double Update(double value) | Recebe o próximo valor (normalmente o fechamento) e devolve o valor da reta no candle atual (NaN no aquecimento). |
Canal de regressão
RegressionChannelCanal de regressão: a reta de mínimos quadrados no meio (Value) e bandas a Deviations erros-padrão dos resíduos (√(Σ(y − reta)²/(N − 2)), as bandas de erro padrão do gráfico). Precisa de N ≥ 3. NaN até ter N valores.
private RegressionChannel canal = null!;public override void OnStart() { canal = new RegressionChannel(50, 2); }public override void OnBarClose(){ canal.Update(Current.Close); // fechou abaixo da banda de baixo: compra mirando o meio do canal if (Position.IsFlat && Current.Close < canal.Lower) Buy(1); else if (Position.IsLong && Current.Close >= canal.Value) ClosePosition();}
| Membro | O que faz |
|---|---|
RegressionChannel(int period = 50, double deviations = 2) | Cria o canal com os últimos period valores (pelo menos 3) e bandas a deviations erros-padrão. |
int Period | O período (em candles). |
double Deviations | A quantos erros-padrão as bandas ficam da reta. |
double Slope | A inclinação da reta: quanto ela anda por candle. |
double StandardError | O erro-padrão dos resíduos (a largura de um desvio). |
double Upper | A banda de cima (reta + desvios × erro-padrão). |
double Lower | A banda de baixo (reta − desvios × erro-padrão). |
double UpperAgo(int barsAgo) | A banda de cima barsAgo candles atrás (0 = agora). |
double LowerAgo(int barsAgo) | A banda de baixo barsAgo candles atrás (0 = agora). |
Output UpperSeries | A banda de cima como série (para Crossed e os utilitários de série). |
Output LowerSeries | A banda de baixo como série (para Crossed e os utilitários de série). |
override double Update(double value) | Recebe o próximo valor (normalmente o fechamento) e devolve a reta no candle atual (NaN no aquecimento); as bandas são atualizadas junto. |
Estocástico
StochasticEstocástico: %K é a posição do fechamento na faixa máxima–mínima dos últimos KPeriod candles, alisada por média simples de KSmoothing; %D é a média simples de DPeriod do %K. Cobre o rápido (suavização 1), o lento (3) e o completo. Mesma conta do Estocástico no gráfico: faixa zero é NaN, não 50. Value é o %K; o %D fica em D.
private Stochastic sto = null!;public override void OnStart() { sto = new Stochastic(14, 3, 3); }public override void OnBarClose(){ sto.Update(Current); // %K cruzou o %D para cima na região de sobrevenda (abaixo de 20) if (Position.IsFlat && sto.K < 20 && Crossed.Above(sto, sto.DSeries)) Buy(1); else if (Position.IsLong && sto.K > 80) ClosePosition();}
| Membro | O que faz |
|---|---|
Stochastic(int kPeriod = 14, int kSmoothing = 3, int dPeriod = 3) | Cria o Estocástico com a faixa de kPeriod candles, o %K alisado por kSmoothing e o %D de dPeriod. |
int KPeriod | Quantos candles entram na faixa máxima–mínima do %K. |
int KSmoothing | A média simples que alisa o %K (1 = Estocástico rápido). |
int DPeriod | O período da média simples do %D. |
double K | O %K (o mesmo que Value). |
double D | O %D (a linha de sinal). |
double DAgo(int barsAgo) | O %D barsAgo candles atrás (0 = agora). |
Output DSeries | O %D como série (para Crossed e os utilitários de série). |
double Update(Candle candle) | Recebe o candle fechado e devolve o %K novo, de 0 a 100 (NaN no aquecimento); o %D é atualizado junto. |
Estocástico do IFR
StochasticRsiEstocástico do RSI: a posição do RSI na própria faixa dos últimos StochasticPeriod valores, alisada como o Estocástico. Mesma conta do Estocástico RSI no gráfico, inclusive o RSI de dentro, que semeia com a média simples das primeiras N variações (diferente de Rsi, que converge de zero): o primeiro RSI sai no candle N + 1. Value é o %K.
private StochasticRsi srsi = null!;public override void OnStart() { srsi = new StochasticRsi(14, 14, 3, 3); }public override void OnBarClose(){ srsi.Update(Current); // saiu da sobrecompra (%K cruzou 80 para baixo): vende if (Position.IsFlat && Crossed.Below(srsi, 80)) Sell(1); else if (Position.IsShort && srsi.K < 20) ClosePosition();}
| Membro | O que faz |
|---|---|
StochasticRsi(int rsiPeriod = 14, int stochasticPeriod = 14, int kSmoothing = 3, int dPeriod = 3) | Cria o Estocástico do RSI: RSI de rsiPeriod, faixa de stochasticPeriod valores, %K alisado por kSmoothing e %D de dPeriod. |
int RsiPeriod | O período do RSI de dentro, em candles. |
int StochasticPeriod | Quantos valores do RSI entram na faixa máxima–mínima. |
int KSmoothing | A média simples que alisa o %K. |
int DPeriod | O período da média simples do %D. |
double K | O %K (o mesmo que Value). |
double D | O %D (a linha de sinal). |
double DAgo(int barsAgo) | O %D barsAgo candles atrás (0 = agora). |
Output DSeries | O %D como série (para Crossed e os utilitários de série). |
double InnerRsi | O RSI de dentro (semeado pela média simples, como no gráfico). |
Output RsiSeries | O RSI de dentro como série (para Crossed e os utilitários de série). |
double Update(double close) | Recebe o fechamento e devolve o %K novo, de 0 a 100 (NaN no aquecimento); o %D e o RSI de dentro são atualizados junto. |
double Update(Candle candle) | O mesmo que Update com o fechamento do candle. |
MACD
MacdMACD: EMA rápida − EMA lenta (Value), a EMA de SignalPeriod dessa diferença (Signal) e a diferença entre as duas (Histogram). Mesma conta do MACD no gráfico: as três EMAs semeiam com o primeiro valor, então há número desde o primeiro candle (zero) e ele converge ao longo do aquecimento.
private Macd macd = null!;public override void OnStart() { macd = new Macd(12, 26, 9); }public override void OnBarClose(){ macd.Update(Current.Close); Plot("Histograma", macd.Histogram, PlotStyle.Histogram); // linha do MACD cruzou a de sinal para cima: compra; para baixo: zera if (Position.IsFlat && Crossed.Above(macd, macd.SignalSeries)) Buy(1); else if (Position.IsLong && Crossed.Below(macd, macd.SignalSeries)) ClosePosition();}
| Membro | O que faz |
|---|---|
Macd(int fastPeriod = 12, int slowPeriod = 26, int signal = 9) | Cria o MACD com a EMA rápida de fastPeriod, a lenta de slowPeriod e o sinal de signal candles. |
int FastPeriod | O período da EMA rápida, em candles. |
int SlowPeriod | O período da EMA lenta, em candles. |
int SignalPeriod | O período da EMA da linha de sinal, em candles. |
double Line | A linha MACD (o mesmo que Value). |
double Signal | A linha de sinal (EMA da linha MACD). |
double Histogram | O histograma (linha MACD − sinal). |
double SignalAgo(int barsAgo) | A linha de sinal barsAgo candles atrás (0 = agora). |
double HistogramAgo(int barsAgo) | O histograma barsAgo candles atrás (0 = agora). |
Output SignalSeries | A linha de sinal como série (para Crossed e os utilitários de série). |
Output HistogramSeries | O histograma como série (para Crossed e os utilitários de série). |
override double Update(double value) | Recebe o próximo valor (normalmente o fechamento) e devolve a linha MACD nova (NaN se o valor não é número); sinal e histograma são atualizados junto. |
Índice de canal de commodities (CCI)
CciCCI (Lambert): (preço típico − média do típico)/(0,015 · desvio médio absoluto) nos últimos N candles, como CCI no gráfico. NaN até ter N candles e quando o desvio é zero.
private Cci cci = null!;public override void OnStart() { cci = new Cci(20); }public override void OnBarClose(){ cci.Update(Current); // voltou de baixo de −100: compra; passou de +100: zera if (Position.IsFlat && Crossed.Above(cci, -100)) Buy(1); else if (Position.IsLong && cci.Value > 100) ClosePosition();}
| Membro | O que faz |
|---|---|
Cci(int period = 20) | Cria o CCI com period candles (padrão 20). |
int Period | O período (em candles). |
double Update(Candle candle) | Recebe o candle fechado e devolve o CCI novo (NaN no aquecimento). |
Williams %R
WilliamsRWilliams %R: (maior máxima − fechamento)/(faixa) × −100 nos últimos N candles, de −100 a 0, como o Williams %R no gráfico. NaN até ter N candles e com faixa zero.
private WilliamsR wr = null!;public override void OnStart() { wr = new WilliamsR(14); }public override void OnBarClose(){ wr.Update(Current); // abaixo de −80 é sobrevenda; acima de −20, sobrecompra if (Position.IsFlat && wr.Value < -80) Buy(1); else if (Position.IsLong && wr.Value > -20) ClosePosition();}
| Membro | O que faz |
|---|---|
WilliamsR(int period = 14) | Cria o Williams %R com period candles (padrão 14). |
int Period | O período (em candles). |
double Update(Candle candle) | Recebe o candle fechado e devolve o %R novo, de −100 a 0 (NaN no aquecimento). |
Padrões de candle
PatternsPadrões de candle, com os MESMOS critérios do catálogo de padrões do gráfico (régua da TA-Lib): corpo e sombras são medidos contra a média dos 10 candles anteriores ao PRIMEIRO candle do padrão (precisa de pelo menos 5), e a tendência que antecede o padrão separa martelo de enforcado e estrela cadente de martelo invertido (tendência = fechamento do candle anterior ao padrão menos a média dos 5 fechamentos antes dele). Sem contexto suficiente, nenhum padrão casa. Todo método recebe a lista de candles e o índice do ÚLTIMO candle do padrão; sem índice, o último da lista (Patterns.Hammer(Candles, Candles.Count - 1) em OnBarClose).
// martelo ou engolfo de alta depois de queda: compra com stop e alvo em pontosif (Position.IsFlat && (Patterns.Hammer(Candles) || Patterns.BullishEngulfing(Candles))){ Buy(1); StopLoss(150); TakeProfit(300);}
| Membro | O que faz |
|---|---|
static bool Doji(IReadOnlyList<Candle> candles, int i) | Corpo de até 10% da amplitude média (indecisão). |
static bool Doji(IReadOnlyList<Candle> candles) | Doji no último candle da lista (o mesmo que passar o índice candles.Count − 1). |
static bool Hammer(IReadOnlyList<Candle> candles, int i) | Corpo pequeno no topo, sombra inferior de pelo menos 2 corpos, quase sem sombra superior, DEPOIS DE QUEDA (alta). |
static bool Hammer(IReadOnlyList<Candle> candles) | Martelo no último candle da lista. |
static bool HangingMan(IReadOnlyList<Candle> candles, int i) | A mesma forma do martelo DEPOIS DE ALTA (baixa). |
static bool HangingMan(IReadOnlyList<Candle> candles) | Enforcado no último candle da lista. |
static bool InvertedHammer(IReadOnlyList<Candle> candles, int i) | Corpo pequeno embaixo, sombra superior de pelo menos 2 corpos, DEPOIS DE QUEDA (alta). |
static bool InvertedHammer(IReadOnlyList<Candle> candles) | Martelo invertido no último candle da lista. |
static bool ShootingStar(IReadOnlyList<Candle> candles, int i) | A mesma forma do martelo invertido DEPOIS DE ALTA (baixa). |
static bool ShootingStar(IReadOnlyList<Candle> candles) | Estrela cadente no último candle da lista. |
static bool BullishMarubozu(IReadOnlyList<Candle> candles, int i) | Candle de alta com corpo longo e quase sem sombras. |
static bool BullishMarubozu(IReadOnlyList<Candle> candles) | Marubozu de alta no último candle da lista. |
static bool BearishMarubozu(IReadOnlyList<Candle> candles, int i) | Candle de baixa com corpo longo e quase sem sombras. |
static bool BearishMarubozu(IReadOnlyList<Candle> candles) | Marubozu de baixa no último candle da lista. |
static bool Marubozu(IReadOnlyList<Candle> candles, int i) | Marubozu de qualquer lado. |
static bool Marubozu(IReadOnlyList<Candle> candles) | Marubozu de qualquer lado no último candle da lista. |
static bool BullishEngulfing(IReadOnlyList<Candle> candles, int i) | Depois de queda, candle de baixa seguido de candle de alta cujo corpo engole o anterior. |
static bool BullishEngulfing(IReadOnlyList<Candle> candles) | Engolfo de alta terminando no último candle da lista. |
static bool BearishEngulfing(IReadOnlyList<Candle> candles, int i) | Depois de alta, candle de alta seguido de candle de baixa cujo corpo engole o anterior. |
static bool BearishEngulfing(IReadOnlyList<Candle> candles) | Engolfo de baixa terminando no último candle da lista. |
static bool BullishHarami(IReadOnlyList<Candle> candles, int i) | Depois de queda, candle de baixa longo seguido de candle de alta menor, com o corpo dentro do anterior. |
static bool BullishHarami(IReadOnlyList<Candle> candles) | Harami de alta terminando no último candle da lista. |
static bool BearishHarami(IReadOnlyList<Candle> candles, int i) | Depois de alta, candle de alta longo seguido de candle de baixa menor, com o corpo dentro do anterior. |
static bool BearishHarami(IReadOnlyList<Candle> candles) | Harami de baixa terminando no último candle da lista. |
static bool MorningStar(IReadOnlyList<Candle> candles, int i) | Depois de queda: baixa longa, corpo curto abaixo dela (com gap no corpo) e alta fechando acima do meio da primeira. Vale também com doji no meio. |
static bool MorningStar(IReadOnlyList<Candle> candles) | Estrela da manhã terminando no último candle da lista. |
static bool EveningStar(IReadOnlyList<Candle> candles, int i) | Depois de alta: alta longa, corpo curto acima dela (com gap no corpo) e baixa fechando abaixo do meio da primeira. Vale também com doji no meio. |
static bool EveningStar(IReadOnlyList<Candle> candles) | Estrela da tarde terminando no último candle da lista. |
static bool ThreeWhiteSoldiers(IReadOnlyList<Candle> candles, int i) | Três candles de alta longos, com pouca sombra superior, cada um fechando acima do anterior e abrindo dentro do corpo do anterior. |
static bool ThreeWhiteSoldiers(IReadOnlyList<Candle> candles) | Três soldados brancos terminando no último candle da lista. |
static bool ThreeBlackCrows(IReadOnlyList<Candle> candles, int i) | Três candles de baixa longos, com pouca sombra inferior, cada um fechando abaixo do anterior e abrindo dentro do corpo do anterior. |
static bool ThreeBlackCrows(IReadOnlyList<Candle> candles) | Três corvos negros terminando no último candle da lista. |
IFR (RSI)
RsiRSI (IFR) de Wilder, 0 a 100. A conta é a mesma do gráfico da HTS: o primeiro valor é NaN (só fixa o fechamento anterior) e, do segundo em diante, as médias de ganho e perda avançam pela suavização de Wilder partindo de zero. Converge ao longo dos primeiros candles em vez de esperar N candles, por isso o valor existe cedo e ainda "assenta".
private Rsi rsi = null!;public override void OnStart() { rsi = new Rsi(14); }public override void OnBarClose(){ rsi.Update(Current.Close); // sobrevendido: compra; voltou a sobrecomprado: zera if (Position.IsFlat && rsi.Value < 30) Buy(1); else if (Position.IsLong && rsi.Value > 70) ClosePosition();}
| Membro | O que faz |
|---|---|
Rsi(int period) | Cria o RSI com period candles na suavização de Wilder. |
int Period | O período (em candles). |
override double Update(double value) | Recebe o próximo valor (normalmente o fechamento) e devolve o RSI novo, de 0 a 100 (NaN no primeiro candle). |
Força da tendência (ADX)
AdxADX de Wilder com as linhas direcionais. Mesma conta do ADX do gráfico: o primeiro candle só fixa o anterior (NaN); no segundo, ATR e DMs são semeados com o próprio valor e o ADX parte de zero; daí em diante tudo avança por suavização de Wilder (α = 1/N). O ADX "assenta" ao longo dos primeiros candles em vez de esperar N candles. Value é o ADX; DiPlus e DiMinus são as direcionais (as do DMI, que usa a mesma semente).
private Adx adx = null!;public override void OnStart() { adx = new Adx(14); }public override void OnBarClose(){ adx.Update(Current); // só opera com tendência forte (ADX acima de 25), a favor da direcional dominante if (Position.IsFlat && adx.Value > 25) { if (adx.DiPlus > adx.DiMinus) Buy(1); else Sell(1); }}
| Membro | O que faz |
|---|---|
Adx(int period = 14) | Cria o ADX com period candles na suavização de Wilder (padrão 14). |
int Period | O período (em candles). |
double DiPlus | O +DI (força da alta), de 0 a 100. |
double DiMinus | O −DI (força da baixa), de 0 a 100. |
double DiPlusAgo(int barsAgo) | O +DI barsAgo candles atrás (0 = agora). |
double DiMinusAgo(int barsAgo) | O −DI barsAgo candles atrás (0 = agora). |
Output DiPlusSeries | O +DI como série (para Crossed e os utilitários de série). |
Output DiMinusSeries | O −DI como série (para Crossed e os utilitários de série). |
double Update(Candle candle) | Recebe o candle fechado e devolve o ADX novo, de 0 a 100 (NaN no primeiro candle); +DI e −DI são atualizados junto. |
SAR parabólico
ParabolicSarSAR parabólico de Wilder, com a conta do SAR parabólico no gráfico: semeia no primeiro candle assumindo alta (SAR na mínima, extremo na máxima); a cada candle avança pelo fator de aceleração, nunca entra na faixa dos dois candles anteriores e, quando é tocado, vira no extremo alcançado. Os primeiros valores são arbitrários por construção. Value é o SAR; IsUptrend diz o lado.
private ParabolicSar sar = null!;public override void OnStart() { sar = new ParabolicSar(0.02, 0.2); }public override void OnBarClose(){ sar.Update(Current); Plot("SAR", sar.Value, PlotStyle.Points); // virou o SAR: zera e entra no lado novo if (sar.FlippedNow) { ClosePosition(); if (sar.IsUptrend) Buy(1); else Sell(1); }}
| Membro | O que faz |
|---|---|
ParabolicSar(double step = 0.02, double max = 0.2) | Cria o SAR com o fator de aceleração começando em step, somando step a cada novo extremo e limitado a max. |
double Step | O passo do fator de aceleração (também o valor inicial). |
double Max | O limite do fator de aceleração. |
bool IsUptrend | O SAR está abaixo do preço (tendência de alta). |
int Direction | +1 em alta, −1 em baixa. |
bool FlippedNow | O SAR virou de lado neste candle. |
double Update(Candle candle) | Recebe o candle fechado e devolve o SAR novo (NaN se máxima ou mínima não é número). |
SuperTrend
SuperTrendSuperTrend: banda de Multiplier·ATR em volta do meio do candle, travada do lado da tendência (só aperta; afrouxa só quando o fechamento a atravessa, e aí a tendência vira). Mesma conta do SuperTrend no gráfico: NaN enquanto o ATR aquece; começa assumindo alta. Value é a linha (o stop); Direction é +1 em alta e −1 em baixa.
private SuperTrend st = null!;public override void OnStart() { st = new SuperTrend(10, 3); }public override void OnBarClose(){ st.Update(Current); Plot("SuperTrend", st.Value); // virou para alta: compra; virou para baixa: zera a compra if (st.FlippedNow && st.IsUptrend && Position.IsFlat) Buy(1); else if (st.FlippedNow && !st.IsUptrend && Position.IsLong) ClosePosition();}
| Membro | O que faz |
|---|---|
SuperTrend(int atrPeriod = 10, double multiplier = 3) | Cria o SuperTrend com ATR de atrPeriod candles e bandas a multiplier ATRs do meio do candle. |
int AtrPeriod | O período do ATR, em candles. |
double Multiplier | Quantos ATRs separam as bandas do meio do candle. |
bool IsUptrend | Tendência de alta: o fechamento não perdeu a banda de baixo, e a linha é essa banda. |
int Direction | +1 em alta, −1 em baixa. |
bool FlippedNow | A tendência virou neste candle. |
double UpperBand | A banda de cima (o stop quando em baixa), mesmo quando a linha está do outro lado. |
double LowerBand | A banda de baixo (o stop quando em alta). |
double Update(Candle candle) | Recebe o candle fechado e devolve a linha do SuperTrend nova (NaN enquanto o ATR aquece). |
HiLo Activator
HiLoHiLo Activator (Gann/Krausz): média das máximas e média das mínimas dos N candles ANTERIORES (sem o atual). Fechou acima da média das máximas: alta, e a linha é a média das mínimas; fechou abaixo da média das mínimas: baixa, e a linha é a média das máximas; entre as duas, vale o lado de antes. Mesma conta do HiLo no gráfico (no primeiro candle entre as médias, o lado mais perto). NaN nos N primeiros candles.
private HiLo hilo = null!;public override void OnStart() { hilo = new HiLo(3); }public override void OnBarClose(){ hilo.Update(Current); Plot("HiLo", hilo.Value, PlotStyle.Step); // o HiLo virou: zera e acompanha o lado novo if (hilo.FlippedNow) { ClosePosition(); if (hilo.IsUptrend) Buy(1); else Sell(1); }}
| Membro | O que faz |
|---|---|
HiLo(int period = 3) | Cria o HiLo com médias de period candles (padrão 3). |
int Period | O período (em candles). |
bool IsUptrend | Lado comprado: o último fechamento fora das médias foi acima da média das máximas, e a linha é a média das mínimas. |
int Direction | +1 em alta, −1 em baixa. |
bool FlippedNow | O HiLo trocou de lado neste candle. |
double HighsAverage | A média das máximas dos N candles anteriores (a linha quando em baixa). |
double LowsAverage | A média das mínimas dos N candles anteriores (a linha quando em alta). |
double Update(Candle candle) | Recebe o candle fechado e devolve a linha do HiLo nova (NaN nos N primeiros candles). |
Aroon
AroonAroon: há quantos candles saiu a máxima (Up) e a mínima (Down) dos últimos N, em percentual (100 = agora, 0 = no começo da janela); Value é o oscilador (alta − baixa). Mesma conta do Aroon, Aroon Down e Aroon Oscillator no gráfico: em empate vale o candle mais recente. NaN até ter N candles.
private Aroon aroon = null!;public override void OnStart() { aroon = new Aroon(25); }public override void OnBarClose(){ aroon.Update(Current); // Aroon Up cruzou o Down para cima: começo de alta if (Position.IsFlat && Crossed.Above(aroon.UpSeries, aroon.DownSeries)) Buy(1); else if (Position.IsLong && Crossed.Below(aroon.UpSeries, aroon.DownSeries)) ClosePosition();}
| Membro | O que faz |
|---|---|
Aroon(int period = 25) | Cria o Aroon com janela de period candles (padrão 25). |
int Period | O período (em candles). |
double Up | Aroon Up. |
double Down | Aroon Down. |
double UpAgo(int barsAgo) | O Aroon Up barsAgo candles atrás (0 = agora). |
double DownAgo(int barsAgo) | O Aroon Down barsAgo candles atrás (0 = agora). |
Output UpSeries | O Aroon Up como série (para Crossed e os utilitários de série). |
Output DownSeries | O Aroon Down como série (para Crossed e os utilitários de série). |
double Update(Candle candle) | Recebe o candle fechado e devolve o oscilador novo (Up − Down, de −100 a 100; NaN no aquecimento); Up e Down são atualizados junto. |
Desvio padrão
StdDevDesvio padrão POPULACIONAL dos últimos N valores (divide por N, como o gráfico da HTS e o ta.stdev do Pine). NaN até ter N valores e se algum não é número.
private StdDev desvio = null!;private Sma media = null!;public override void OnStart() { desvio = new StdDev(20); media = new Sma(20); }public override void OnBarClose(){ desvio.Update(Current.Close); media.Update(Current.Close); // filtro: mercado parado (desvio pequeno) não entra if (desvio.IsReady && desvio.Value > 30 && Position.IsFlat && Crossed.Above(Closes, media)) Buy();}
| Membro | O que faz |
|---|---|
StdDev(int period = 20) | Cria o desvio padrão com period candles (1 a 500). |
int Period | O período (em candles). |
override double Update(double value) | Avança um candle com um valor (o fechamento, outro indicador...) e devolve o desvio padrão novo (NaN no aquecimento). |
Volatilidade histórica
HistoricalVolatilityVolatilidade histórica: desvio padrão (populacional) dos últimos N log-retornos (ln(fechamento/anterior)), vezes a raiz de Annualization (252 pregões), em percentual. Mesma conta do volatilidade histórica no gráfico. O primeiro candle não tem retorno, então o primeiro valor sai no candle N + 1. Retorno com preço zero ou negativo é NaN e invalida a janela.
private HistoricalVolatility volatilidade = null!;public override void OnStart() { volatilidade = new HistoricalVolatility(20, 252); }public override void OnBarClose(){ volatilidade.Update(Current.Close); Plot("Vol. histórica %", volatilidade.Value); // avisa no log quando a volatilidade passa de 40% ao ano if (volatilidade.IsReady && volatilidade.Value > 40) Log("Volatilidade acima de 40% ao ano");}
| Membro | O que faz |
|---|---|
HistoricalVolatility(int period = 20, int annualization = 252) | Cria a volatilidade histórica com period log-retornos, anualizada por annualization períodos por ano (252 pregões no diário). |
int Period | O período (em log-retornos, um por candle). |
int Annualization | Quantos períodos há num ano para anualizar (o desvio é multiplicado pela raiz deste número). Mínimo 1. |
override double Update(double value) | Avança um candle com um preço (normalmente o fechamento) e devolve a volatilidade nova, em % (NaN no aquecimento). |
Saldo de volume (OBV)
ObvOBV (Granville): soma o volume quando o fechamento sobe, subtrai quando cai, não mexe quando empata. Mesma conta do OBV no gráfico: começa em zero no primeiro candle (o nível não quer dizer nada, só a direção).
private Obv obv = null!;private Ema mediaDoObv = null!;public override void OnStart() { obv = new Obv(); mediaDoObv = new Ema(20); }public override void OnBarClose(){ obv.Update(Current); mediaDoObv.Update(obv.Value); // o volume confirma a alta: OBV cruza a própria média para cima if (Position.IsFlat && Crossed.Above(obv, mediaDoObv)) Buy();}
| Membro | O que faz |
|---|---|
double Update(Candle candle) | Avança com o candle fechado (fechamento e volume) e devolve o OBV novo. |
Acumulação e distribuição
AccumulationDistributionLinha de acumulação/distribuição (Chaikin): acumula volume × posição do fechamento na faixa do candle (−1 a +1). Mesma conta do linha A/D no gráfico: candle com faixa zero não mexe na linha (repete o valor).
private AccumulationDistribution ad = null!;public override void OnStart() { ad = new AccumulationDistribution(); }public override void OnBarClose(){ ad.Update(Current); Plot("A/D", ad.Value); // divergência: preço caindo e a linha A/D subindo (acumulação) if (Current.Close < Closes[5] && ad.Value > ad[5]) Log("Acumulação na queda");}
| Membro | O que faz |
|---|---|
double Update(Candle candle) | Avança com o candle fechado (máxima, mínima, fechamento e volume) e devolve a linha A/D nova (NaN até o primeiro candle com faixa). |
Oscilador de Chaikin
ChaikinOscillatorOscilador de Chaikin: EMA rápida − EMA lenta da linha de acumulação/distribuição (o MACD do fluxo). Mesma conta do Chaikin Oscillator no gráfico: valor desde o primeiro candle (zero), convergindo.
private ChaikinOscillator chaikin = null!;public override void OnStart() { chaikin = new ChaikinOscillator(3, 10); }public override void OnBarClose(){ chaikin.Update(Current); // fluxo virou comprador: oscilador cruza o zero para cima if (Position.IsFlat && Crossed.Above(chaikin, 0)) Buy(); else if (Position.IsLong && Crossed.Below(chaikin, 0)) ClosePosition();}
| Membro | O que faz |
|---|---|
ChaikinOscillator(int fastPeriod = 3, int slowPeriod = 10) | Cria o oscilador com a EMA rápida de fastPeriod candles e a lenta de slowPeriod candles. |
int FastPeriod | O período da EMA rápida (em candles). |
int SlowPeriod | O período da EMA lenta (em candles). |
double Update(Candle candle) | Avança com o candle fechado (máxima, mínima, fechamento e volume) e devolve o oscilador novo (NaN até o primeiro candle com faixa). |
Índice de força
ForceIndexForce Index (Elder): EMA de (fechamento − fechamento anterior) × volume. Mesma conta do Force Index no gráfico: NaN no primeiro candle; a EMA semeia com o primeiro produto.
private ForceIndex forca = null!;private Ema tendencia = null!;public override void OnStart() { forca = new ForceIndex(2); tendencia = new Ema(50); }public override void OnBarClose(){ forca.Update(Current); tendencia.Update(Current.Close); // Elder: tendência de alta e força negativa (correção) = ponto de compra if (Position.IsFlat && Current.Close > tendencia.Value && forca.Value < 0) Buy();}
| Membro | O que faz |
|---|---|
ForceIndex(int period = 13) | Cria o Force Index com EMA de period candles (1 a 500). |
int Period | O período da EMA (em candles). |
double Update(Candle candle) | Avança com o candle fechado (fechamento e volume) e devolve o Force Index novo (NaN no primeiro candle). |
Tendência preço-volume (PVT)
PvtPVT (Price Volume Trend): acumula volume × variação percentual do fechamento. Mesma conta do PVT no gráfico: NaN no primeiro candle (não há variação); depois parte de zero.
private Pvt pvt = null!;private Sma sinal = null!;public override void OnStart() { pvt = new Pvt(); sinal = new Sma(21); }public override void OnBarClose(){ pvt.Update(Current); sinal.Update(pvt.Value); Plot("PVT", pvt.Value); Plot("Sinal", sinal.Value); if (Position.IsLong && Crossed.Below(pvt, sinal)) ClosePosition();}
| Membro | O que faz |
|---|---|
double Update(Candle candle) | Avança com o candle fechado (fechamento e volume) e devolve o PVT novo (NaN no primeiro candle). |
Ondas de Weis
WeisWaveWeis Wave: o volume acumulado da onda atual. Não existe no gráfico da HTS; a regra aqui é a clássica de David Weis sem filtro de tamanho: a onda de alta segue enquanto o fechamento não cai abaixo do maior fechamento da onda (menos Reversal pontos, quando informado); quando cai, começa uma onda de baixa naquele candle, com o volume dele, e vice-versa. Fechamento igual continua a onda. A primeira onda tem o lado do primeiro candle (de alta se fechou acima de onde abriu, senão de baixa). Value é o volume da onda com sinal (positivo na alta, negativo na baixa); WaveVolume é o módulo; PreviousWave é o volume (com sinal) da onda que acabou.
private WeisWave ondas = null!;public override void OnStart() { ondas = new WeisWave(50); }public override void OnBarClose(){ ondas.Update(Current); Plot("Onda", ondas.Value, PlotStyle.Histogram); // começou uma onda de alta: mostra quanto volume teve a onda de baixa que acabou if (ondas.FlippedNow && ondas.IsUptrend) Log($"Nova onda de alta; a de baixa somou {Math.Abs(ondas.PreviousWave)} contratos");}
| Membro | O que faz |
|---|---|
WeisWave(double reversal = 0) | Cria o Weis Wave; a onda só vira quando o fechamento recua mais que reversal pontos do extremo (0 = qualquer recuo). |
double Reversal | Quanto o fechamento precisa andar contra o extremo da onda para virar (0 = qualquer recuo). |
bool IsUptrend | A onda atual é de alta. |
int Direction | O lado da onda atual: +1 na alta, −1 na baixa. |
bool FlippedNow | Uma onda nova começou neste candle. |
double WaveVolume | O volume da onda atual, sem sinal. |
double PreviousWave | O volume (com sinal) da onda que acabou de terminar; NaN antes da primeira virada. |
int BarsInWave | Candles na onda atual (contando o atual). |
double WaveExtreme | O fechamento extremo da onda atual (o maior na alta, o menor na baixa). |
double Update(Candle candle) | Avança com o candle fechado (abertura, fechamento e volume) e devolve o volume da onda com sinal. |
VWAP
VwapVWAP por período: Σ(preço·volume)/Σ(volume) acumulado desde o início do dia, da semana ou do mês, zerando na virada (pela Date em Brasília e PeriodKey). A conta é a do VWAP do gráfico: o preço é o FECHAMENTO do candle (não o preço típico), e o valor existe desde o primeiro candle do período. Com typicalPrice: true a conta usa (máxima + mínima + fechamento)/3, como outras plataformas. Volume zero no período inteiro dá NaN.
private Vwap vwap = null!;public override void OnStart() { vwap = new Vwap(Period.Day); }public override void OnBarClose(){ vwap.Update(Current); Plot("VWAP", vwap.Value); // compra quando o preço retoma o VWAP do dia if (Position.IsFlat && Crossed.Above(Closes, vwap)) Buy();}
| Membro | O que faz |
|---|---|
Vwap(Period period = Period.Day, bool typicalPrice = false) | Cria o VWAP que zera a cada period (dia, semana ou mês); com typicalPrice a conta usa o preço típico em vez do fechamento. |
Period Period | De quanto em quanto tempo o VWAP zera (dia, semana ou mês). |
bool TypicalPrice | A conta usa o preço típico, (máxima + mínima + fechamento)/3, em vez do fechamento. |
double Update(Candle candle) | Avança com o candle fechado (preço e volume) e devolve o VWAP novo; zera na virada do período. |
VWAP ancorado
AnchoredVwapVWAP ancorado: acumula desde o candle em que o robô chamou Anchor (um rompimento, a abertura de um evento, um topo). Antes da primeira âncora o valor é NaN. Chame Anchor() ANTES de Update(Current) no mesmo candle para que o candle da âncora entre na conta.
private Highest maxima = null!;private AnchoredVwap vwap = null!;public override void OnStart() { maxima = new Highest(20); vwap = new AnchoredVwap(); }public override void OnBarClose(){ maxima.Update(Current); // ancora o VWAP no candle que rompeu a máxima dos 20 anteriores (antes do Update) if (Current.Close > maxima[1]) vwap.Anchor(); vwap.Update(Current); if (vwap.IsReady) Plot("VWAP ancorado", vwap.Value);}
| Membro | O que faz |
|---|---|
AnchoredVwap(bool typicalPrice = false) | Cria o VWAP ancorado, ainda sem âncora; com typicalPrice a conta usa o preço típico em vez do fechamento. |
bool TypicalPrice | A conta usa o preço típico, (máxima + mínima + fechamento)/3, em vez do fechamento. |
bool IsAnchored | Há uma âncora (o indicador está acumulando). |
int BarsSinceAnchor | Candles acumulados desde a âncora (0 sem âncora). |
void Anchor() | Zera a acumulação: o próximo Update começa um VWAP novo. |
double Update(Candle candle) | Avança com o candle fechado (preço e volume) e devolve o VWAP desde a âncora (NaN antes da primeira âncora). |