# MQR: Manual para IAs que Criam Estrategias

> Este arquivo usa somente caracteres ASCII de proposito. Assim ele permanece
> legivel em qualquer editor, sem depender de configuracao de codificacao.

## 1. Objetivo

Este documento define o contrato publico para uma IA criar, alterar, revisar e
depurar arquivos de estrategia `.mqr`.

MQR possui sintaxe parecida com C/C++/MQL5, mas nao e MQL5. Gere somente
recursos descritos neste manual ou em `MQR_Referencia.md`.

Nao use, nao cite como dependencia e nao tente reproduzir detalhes internos da
engine. Uma estrategia deve depender apenas da linguagem e das funcoes publicas.

## 2. Instrucoes obrigatorias para a IA

Ao receber um pedido de estrategia MQR:

1. Identifique timeframe, sinais de compra/venda, entrada, saida, TP, SL,
   lote, horarios, filtros e regra para posicao existente.
2. Pergunte quando faltar uma decisao que altere o risco ou a semantica.
3. Use `OnBarOpen()` para sinais e entradas baseados no candle do timeframe.
4. Use `OnBarOpenM1()` somente para gestao que exige precisao M1.
5. Use `Close[1]`, indicadores com offset `1` e candles anteriores para
   sinais confirmados.
6. Valide historico antes de acessar candles ou indicadores.
7. Calcule TP e SL como precos absolutos.
8. Normalize todos os precos enviados para ordens.
9. Use somente APIs listadas neste documento.
10. Entregue um arquivo `.mqr` completo, sem pseudocodigo.

## 3. O que nao pode ser usado

MQR nao oferece automaticamente recursos do MQL5. Nao gerar:

- `#include`, classes, objetos, handles ou `CopyBuffer`;
- `iMA`, `iBands`, `iRSI`, `CTrade`, `MqlRates`, `OrderSend`;
- arquivos, DLL, rede, banco de dados ou chamadas ao sistema;
- strings como estrutura de dados da estrategia;
- APIs nao documentadas neste manual.

Se uma regra MQL5 depender de uma API nao listada, reprojete a regra usando os
dados e indicadores publicos de MQR.

---

## 4. Modelo de execucao

### 4.1 Eventos

| Evento | Quando usar |
|---|---|
| `OnInit()` | Executa uma vez. Define o timeframe e inicializa globais. |
| `OnBarOpen()` | Executa na abertura de cada candle do TF principal. Use para sinais e entradas. |
| `OnBarOpenM1()` | Opcional. Executa a cada M1. Use para horario, trailing e gestao M1. |

Toda estrategia com timeframe configuravel deve conter:

```cpp
void OnInit() {
    SetTimeFrame(inpTimeFrame);
}
```

### 4.2 Indices de candle

| Indice | Significado em `OnBarOpen()` |
|---|---|
| `[0]` | Candle em formacao; no inicio representa o preco de abertura/corrente. |
| `[1]` | Ultimo candle totalmente fechado. |
| `[2]` | Candle fechado anterior a `[1]`. |

Padrao seguro para sinais:

```cpp
double media = EMA(21, 1);
bool compra = Close[1] > media;
```

Evite usar `Close[0]` ou indicadores com offset `0` para confirmar entrada:
esses valores pertencem ao candle em formacao.

Uma ordem enviada em `OnBarOpen()` vale a partir do novo candle. Nao atrase a
ordem para o proximo candle sem que esse atraso seja uma regra explicita da
estrategia.

### 4.3 Historico minimo

Antes de acessar `Close[n]` ou indicador de periodo `p`, garanta barras
suficientes:

```cpp
int minBarras = Max(inpMediaRapida, inpMediaLenta) + 2;
if (BarIndex() < minBarras) return;
```

Para outro timeframe:

```cpp
if (BarCountTF(PERIOD_H1) < 30) return;
```

---

## 5. Estrutura recomendada

Organize o arquivo nesta ordem:

1. Comentario de descricao.
2. Enums.
3. Inputs e grupos.
4. Variaveis globais.
5. Funcoes auxiliares.
6. `OnInit`.
7. `OnBarOpenM1` (se necessario).
8. `OnBarOpen`.

Modelo base:

```cpp
enum ENUM_DIRECAO {
    COMPRA = 0,  // Apenas compra
    VENDA = 1,   // Apenas venda
    AMBOS = 2    // Compra e venda
};

input group "Timeframe"
input ENUM_TIMEFRAMES inpTimeFrame = PERIOD_M5; // Timeframe

input group "Risco"
input double inpLote = 1.0;  // Lotes
input double inpTP = 100.0;  // Alvo em pontos
input double inpSL = 100.0;  // Stop em pontos

input group "Filtro"
input ENUM_DIRECAO inpDirecao = AMBOS; // Direcao permitida

void OnInit() {
    SetTimeFrame(inpTimeFrame);
}

void OnBarOpen() {
    if (BarIndex() < 25) return;
    if (PositionsTotal() > 0) return;

    // Sinal e envio de ordem.
}
```

---

## 6. Tipos, variaveis e fluxo

### 6.1 Tipos permitidos

```cpp
double preco = 0.0;
int contador = 0;
bool ativo = false;
double valores[];
int indices[];
```

Tipos principais: `double`, `int`, `bool`, `ENUM_TIMEFRAMES`, enums
customizados, arrays de `double` e arrays de `int`.

Armazene tickets em `double`:

```cpp
double ticket = BuyLimit(1.0, preco, sl, tp);
```

### 6.2 Fluxo e operadores

Suportados:

```cpp
if (...) { } else { }
for (int i = 0; i < 10; i++) { }
while (...) { }
do { } while (...);
switch (valor) { case 1: break; default: break; }
break;
continue;
return;
```

Operadores:

```text
+ - * / %
= -= *= /= ++ --
== != < > <= >=
&& || !
```

### 6.3 Arrays

```cpp
double closes[];
ArrayResize(closes, 5);
closes[0] = Close[1];
int tamanho = ArraySize(closes);
```

Nao use indice negativo nem indice maior ou igual ao tamanho do array.

---

## 7. Inputs, enums e otimizacao

Input fixo:

```cpp
input double inpFator = 1.5; // Fator
```

Input otimizavel:

```cpp
input int inpPeriodo = 20 [5, 1, 60];        // Periodo
input double inpFator = 1.5 [0.5, 0.1, 3.0]; // Fator
```

Use `input group` para organizar a tela:

```cpp
input group "Gestao de Risco"
input double inpLote = 1.0; // Lotes
input double inpTP = 100;   // Take Profit
input double inpSL = 100;   // Stop Loss
```

Use enums para escolhas discretas:

```cpp
enum ENUM_HORA {
    H0905 = 905,   // 09:05
    H1700 = 1700,  // 17:00
    H1730 = 1730   // 17:30
};

input ENUM_HORA inpHoraFim = H1700; // Hora limite
```

O comentario na mesma linha de input ou item do enum e usado como rotulo.

---

## 8. Dados de mercado e tempo

| Recurso | Uso |
|---|---|
| `Open[n]`, `High[n]`, `Low[n]`, `Close[n]` | OHLC no timeframe principal. |
| `Volume[n]` | Volume de ticks. |
| `Time[n]` | Timestamp numerico da barra. |
| `BarIndex()` | Indice da barra atual. |
| `BarCount()` | Total de barras disponiveis. |
| `Hour()`, `Minute()` | Hora e minuto da barra atual. |
| `DayOfWeek()` | 0 domingo ate 6 sabado. |
| `IsFirstBarOfDay()` | Verdadeiro na primeira barra do dia. |
| `IsLastBarOfDay()` | Verdadeiro na ultima barra do dia. |

Funcao auxiliar de horario:

```cpp
int HoraHHMM() {
    return Hour() * 100 + Minute();
}

bool DentroDoHorario(int inicio, int fim) {
    int agora = HoraHHMM();
    return agora >= inicio && agora < fim;
}
```

---

## 9. Indicadores do timeframe principal

Todos aceitam `offset`. Para sinais confirmados, use `offset = 1`.

| Indicador | Assinatura |
|---|---|
| Media simples | `SMA(periodo, offset)` |
| Media exponencial | `EMA(periodo, offset)` |
| RSI | `RSI(periodo, offset)` |
| ATR | `ATR(periodo, offset)` |
| CCI | `CCI(periodo, offset)` |
| Z-Score | `ZScore(periodo, offset)` |
| MACD | `MACD(rapida, lenta, sinal, offset)` |
| Sinal MACD | `MACDSignal(rapida, lenta, sinal, offset)` |
| Histograma MACD | `MACDHist(rapida, lenta, sinal, offset)` |
| Banda superior | `BollingerUpper(periodo, desvio, offset)` |
| Banda inferior | `BollingerLower(periodo, desvio, offset)` |
| Estocastico K | `StochK(periodoK, periodoD, offset)` |
| Estocastico D | `StochD(periodoK, periodoD, offset)` |
| Keltner superior | `KeltnerUpper(periodoEMA, periodoATR, multiplicador, offset)` |
| Keltner inferior | `KeltnerLower(periodoEMA, periodoATR, multiplicador, offset)` |

Exemplo de cruzamento confirmado:

```cpp
double rapidaAgora = EMA(9, 1);
double lentaAgora = EMA(21, 1);
double rapidaAntes = EMA(9, 2);
double lentaAntes = EMA(21, 2);

bool cruzouParaCima = rapidaAntes <= lentaAntes &&
                       rapidaAgora > lentaAgora;
```

Indicadores podem retornar `0` sem historico suficiente. Sempre valide as
barras antes de interpretar esse valor.

---

## 10. Multi-timeframe

O primeiro argumento de uma funcao MTF e o timeframe em minutos ou uma
constante `PERIOD_*`.

### 10.1 Dados MTF

```cpp
OpenTF(tf, offset)
HighTF(tf, offset)
LowTF(tf, offset)
CloseTF(tf, offset)
VolumeTF(tf, offset)
TimeTF(tf, offset)
```

`CloseTF(tf, 0)` retorna o fechamento/preco corrente da barra em formacao no
timeframe externo. Para um sinal confirmado, use `CloseTF(tf, 1)`, que retorna
o fechamento da ultima barra completada.

### 10.2 Indicadores MTF

```cpp
SMATF(tf, periodo, offset)
EMATF(tf, periodo, offset)
RSITF(tf, periodo, offset)
ATRTF(tf, periodo, offset)
CCITF(tf, periodo, offset)
ZScoreTF(tf, periodo, offset)

MACDTF(tf, rapida, lenta, sinal, offset)
MACDSignalTF(tf, rapida, lenta, sinal, offset)
MACDHistTF(tf, rapida, lenta, sinal, offset)

BollingerUpperTF(tf, periodo, desvio, offset)
BollingerLowerTF(tf, periodo, desvio, offset)
StochKTF(tf, periodoK, periodoD, offset)
StochDTF(tf, periodoK, periodoD, offset)
KeltnerUpperTF(tf, periodoEMA, periodoATR, multiplicador, offset)
KeltnerLowerTF(tf, periodoEMA, periodoATR, multiplicador, offset)
```

### 10.3 Estado do timeframe

```cpp
BarCountTF(tf)
IsBarCompleteTF(tf)
IsFirstBarOfDayTF(tf)
IsLastBarOfDayTF(tf)
SetTimeFrame(tf)
GetTimeFrame()
IsNewBar()
IsNewBar(tf)
```

Exemplo de filtro H1 em estrategia M5:

```cpp
if (BarCountTF(PERIOD_H1) < 30) return;

double emaH1 = EMATF(PERIOD_H1, 21, 1);
bool altaH1 = CloseTF(PERIOD_H1, 1) > emaH1;

if (altaH1 && Close[1] > EMA(9, 1)) {
    // Compra permitida.
}
```

---

## 11. Contrato de trade

### 11.1 Regra essencial: preco absoluto

Os argumentos de entrada, stop e alvo sao precos absolutos.

Para compra:

```cpp
double entrada = NormalizePrice(Close[0]);
double sl = NormalizePrice(entrada - inpSL);
double tp = NormalizePrice(entrada + inpTP);
Buy(inpLote, sl, tp);
```

Para venda:

```cpp
double entrada = NormalizePrice(Close[0]);
double sl = NormalizePrice(entrada + inpSL);
double tp = NormalizePrice(entrada - inpTP);
Sell(inpLote, sl, tp);
```

Use `0` para informar que nao existe SL ou TP.

### 11.2 Aberturas

| Objetivo | Funcao |
|---|---|
| Compra a mercado | `Buy(lotes, sl, tp)` |
| Venda a mercado | `Sell(lotes, sl, tp)` |
| Comprar no recuo | `BuyLimit(lotes, preco, sl, tp)` |
| Vender no repique | `SellLimit(lotes, preco, sl, tp)` |
| Comprar no rompimento | `BuyStop(lotes, preco, sl, tp)` |
| Vender no rompimento | `SellStop(lotes, preco, sl, tp)` |

### 11.3 Gestao

| Acao | Funcao |
|---|---|
| Fechar uma posicao | `ClosePosition(ticket)` |
| Fechar posicoes | `CloseAllPositions()` |
| Excluir uma ordem | `OrderDelete(ticket)` |
| Cancelar ordens | `CancelAllOrders()` |
| Fechar tudo | `CloseAll()` |
| Alterar SL/TP | `PositionModify(ticket, sl, tp)` |
| Alterar ordem | `OrderModify(ticket, preco, sl, tp)` |

### 11.4 Consultas

```cpp
PositionsTotal()
PositionTicket(indice)
PositionEntry(ticket)
PositionSL(ticket)
PositionTP(ticket)
PositionLots(ticket)
PositionProfit(ticket)
PositionType(ticket)

OrdersTotal()
OrderTicket(indice)
OrderPrice(ticket)
OrderSL(ticket)
OrderTP(ticket)
OrderLots(ticket)
OrderType(ticket)
```

Constantes publicas:

```cpp
POSITION_TYPE_BUY
POSITION_TYPE_SELL

ORDER_TYPE_BUY
ORDER_TYPE_SELL
ORDER_TYPE_BUY_LIMIT
ORDER_TYPE_SELL_LIMIT
ORDER_TYPE_BUY_STOP
ORDER_TYPE_SELL_STOP
```

Ao alterar ou excluir varias ordens, reconsulte a lista depois de cada
operacao. Nao reutilize um indice antigo supondo que ele aponta para a mesma
ordem.

### 11.5 Tick, normalizacao e PnL

| Funcao | Finalidade |
|---|---|
| `TickSize()` | Menor variacao valida de preco. |
| `TickValue()` | Valor financeiro de um tick por lote. |
| `Digits()` | Casas decimais do ativo. |
| `NormalizePrice(preco)` | Ajusta o preco para um valor negociavel. |

Exemplo seguro de ordem pendente:

```cpp
double preco = NormalizePrice(Low[1] - TickSize());
double sl = NormalizePrice(preco - inpSL);
double tp = NormalizePrice(preco + inpTP);
BuyLimit(inpLote, preco, sl, tp);
```

---

## 12. Padroes seguros de estrategia

### 12.1 Uma posicao por vez

Use por padrao:

```cpp
if (PositionsTotal() > 0) return;
```

Remova isso somente se a solicitacao exigir piramidacao ou multiplas posicoes.

### 12.2 Substituir ordem pendente

```cpp
if (sinalCompra) {
    if (OrdersTotal() > 0) CancelAllOrders();

    double preco = NormalizePrice(Open[1]);
    BuyLimit(inpLote, preco,
             NormalizePrice(preco - inpSL),
             NormalizePrice(preco + inpTP));
}
```

### 12.3 Encerrar no horario com precisao M1

```cpp
void OnBarOpenM1() {
    int agora = Hour() * 100 + Minute();
    if (agora >= 1730 && (PositionsTotal() > 0 || OrdersTotal() > 0)) {
        CloseAll();
    }
}
```

### 12.4 Breakeven simples

```cpp
void AjustarBreakeven() {
    if (PositionsTotal() <= 0) return;

    double ticket = PositionTicket(0);
    double entrada = PositionEntry(ticket);

    if (PositionType(ticket) == POSITION_TYPE_BUY &&
        Close[0] >= entrada + 100) {
        PositionModify(ticket, entrada, PositionTP(ticket));
    }
    else if (PositionType(ticket) == POSITION_TYPE_SELL &&
             Close[0] <= entrada - 100) {
        PositionModify(ticket, entrada, PositionTP(ticket));
    }
}
```

### 12.5 Ordem correta para horario

Primeiro encerre o que e obrigatorio. Depois bloqueie entradas:

```cpp
void OnBarOpen() {
    int agora = Hour() * 100 + Minute();

    if (agora >= 1730) {
        CloseAll();
        return;
    }

    if (agora < 905 || agora >= 1700) {
        if (agora >= 1700) CancelAllOrders();
        return;
    }

    // Avaliar entradas aqui.
}
```

---

## 13. Matematica e debug

Funcoes matematicas:

```cpp
Abs(x)
Max(a, b)
Min(a, b)
Sqrt(x)
Round(x)
Floor(x)
Ceil(x)
Pow(base, expoente)
```

Use `Print` apenas para depuracao:

```cpp
Print("RSI=" + RSI(14, 1) + " close=" + Close[1]);
```

---

## 14. Escolha do modo de backtest

| Caso | Modo recomendado |
|---|---|
| Busca inicial de parametros sem gestao M1 | TimeFrame do input |
| Validacao final | M1 OHLC |
| Ordens pendentes, trailing, breakeven ou horario por minuto | M1 OHLC |
| Estrategia com `OnBarOpenM1()` | M1 OHLC |

Se TP e SL puderem ser atingidos na mesma barra, trate o resultado como
conservador: SL tem prioridade.

---

## 15. Checklist antes de entregar MQR

- [ ] Existe `SetTimeFrame(inpTimeFrame)` em `OnInit`.
- [ ] O maior periodo e offset possuem historico validado.
- [ ] Sinais usam candles fechados, salvo requisito explicito.
- [ ] TP e SL sao precos absolutos.
- [ ] Entrada, SL e TP usam `NormalizePrice`.
- [ ] Compra possui SL abaixo e TP acima da entrada.
- [ ] Venda possui SL acima e TP abaixo da entrada.
- [ ] Posicoes e ordens pendentes existentes sao tratadas.
- [ ] Horario de fechamento chama `CloseAll` quando solicitado.
- [ ] O filtro de direcao e aplicado de forma consistente.
- [ ] Nenhuma API de MQL5 ou funcao nao documentada foi usada.
- [ ] O resultado e um unico arquivo `.mqr` completo e compilavel.

## 16. Formato de resposta para outra IA

Ao implementar uma estrategia, responda nesta ordem:

1. Resumo curto das regras entendidas.
2. Perguntas apenas para requisitos que alteram risco ou comportamento.
3. Arquivo `.mqr` completo.
4. Premissas adotadas.
5. Modo de backtest recomendado.

Nao afirme que uma estrategia e lucrativa. O resultado depende de dados,
ativo, custos, parametros e modelo de execucao.
