mtcli-risco 2.3.0.dev1__tar.gz → 2.3.0.dev2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {mtcli_risco-2.3.0.dev1 → mtcli_risco-2.3.0.dev2}/PKG-INFO +1 -1
- {mtcli_risco-2.3.0.dev1 → mtcli_risco-2.3.0.dev2}/mtcli_risco/models/panic_model.py +61 -25
- {mtcli_risco-2.3.0.dev1 → mtcli_risco-2.3.0.dev2}/pyproject.toml +1 -1
- {mtcli_risco-2.3.0.dev1 → mtcli_risco-2.3.0.dev2}/LICENSE +0 -0
- {mtcli_risco-2.3.0.dev1 → mtcli_risco-2.3.0.dev2}/README.md +0 -0
- {mtcli_risco-2.3.0.dev1 → mtcli_risco-2.3.0.dev2}/mtcli_risco/__init__.py +0 -0
- {mtcli_risco-2.3.0.dev1 → mtcli_risco-2.3.0.dev2}/mtcli_risco/cli.py +0 -0
- {mtcli_risco-2.3.0.dev1 → mtcli_risco-2.3.0.dev2}/mtcli_risco/commands/__init__.py +0 -0
- {mtcli_risco-2.3.0.dev1 → mtcli_risco-2.3.0.dev2}/mtcli_risco/commands/checar.py +0 -0
- {mtcli_risco-2.3.0.dev1 → mtcli_risco-2.3.0.dev2}/mtcli_risco/commands/monitorar.py +0 -0
- {mtcli_risco-2.3.0.dev1 → mtcli_risco-2.3.0.dev2}/mtcli_risco/commands/panic.py +0 -0
- {mtcli_risco-2.3.0.dev1 → mtcli_risco-2.3.0.dev2}/mtcli_risco/commands/trades.py +0 -0
- {mtcli_risco-2.3.0.dev1 → mtcli_risco-2.3.0.dev2}/mtcli_risco/conf.py +0 -0
- {mtcli_risco-2.3.0.dev1 → mtcli_risco-2.3.0.dev2}/mtcli_risco/models/__init__.py +0 -0
- {mtcli_risco-2.3.0.dev1 → mtcli_risco-2.3.0.dev2}/mtcli_risco/models/checar_model.py +0 -0
- {mtcli_risco-2.3.0.dev1 → mtcli_risco-2.3.0.dev2}/mtcli_risco/models/trades_model.py +0 -0
- {mtcli_risco-2.3.0.dev1 → mtcli_risco-2.3.0.dev2}/mtcli_risco/plugin.py +0 -0
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Modo PANIC CLOSE.
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
-
|
|
6
|
-
-
|
|
7
|
-
-
|
|
4
|
+
Responsável por:
|
|
5
|
+
- Encerrar TODAS as posições abertas (hedge ou netting)
|
|
6
|
+
- Cancelar TODAS as ordens pendentes
|
|
7
|
+
- Funcionar com market aberto ou fechado (retry automático)
|
|
8
|
+
- Suportar modo DRY-RUN (simulação)
|
|
8
9
|
"""
|
|
9
10
|
|
|
10
11
|
import time
|
|
@@ -16,16 +17,25 @@ log = setup_logger()
|
|
|
16
17
|
|
|
17
18
|
|
|
18
19
|
def _trade_permitido() -> bool:
|
|
20
|
+
"""
|
|
21
|
+
Verifica se a conta permite trading.
|
|
22
|
+
"""
|
|
19
23
|
info = mt5.account_info()
|
|
20
24
|
return bool(info and info.trade_allowed)
|
|
21
25
|
|
|
22
26
|
|
|
23
27
|
def _market_aberto(symbol: str) -> bool:
|
|
28
|
+
"""
|
|
29
|
+
Verifica se o mercado do símbolo está aberto para trading.
|
|
30
|
+
"""
|
|
24
31
|
info = mt5.symbol_info(symbol)
|
|
25
32
|
return bool(info and info.trade_mode == mt5.SYMBOL_TRADE_MODE_FULL)
|
|
26
33
|
|
|
27
34
|
|
|
28
35
|
def _close_position(position, dry_run: bool = False) -> bool:
|
|
36
|
+
"""
|
|
37
|
+
Fecha uma posição individual (compatível com hedge e netting).
|
|
38
|
+
"""
|
|
29
39
|
symbol = position.symbol
|
|
30
40
|
tick = mt5.symbol_info_tick(symbol)
|
|
31
41
|
|
|
@@ -33,19 +43,19 @@ def _close_position(position, dry_run: bool = False) -> bool:
|
|
|
33
43
|
log.error(f"[PANIC] Tick indisponível para {symbol}")
|
|
34
44
|
return False
|
|
35
45
|
|
|
36
|
-
|
|
46
|
+
order_type = (
|
|
37
47
|
mt5.ORDER_TYPE_SELL
|
|
38
48
|
if position.type == mt5.ORDER_TYPE_BUY
|
|
39
49
|
else mt5.ORDER_TYPE_BUY
|
|
40
50
|
)
|
|
41
51
|
|
|
42
|
-
price = tick.bid if
|
|
52
|
+
price = tick.bid if order_type == mt5.ORDER_TYPE_SELL else tick.ask
|
|
43
53
|
|
|
44
54
|
request = {
|
|
45
55
|
"action": mt5.TRADE_ACTION_DEAL,
|
|
46
56
|
"symbol": symbol,
|
|
47
57
|
"volume": position.volume,
|
|
48
|
-
"type":
|
|
58
|
+
"type": order_type,
|
|
49
59
|
"price": price,
|
|
50
60
|
"deviation": 20,
|
|
51
61
|
"magic": 999999,
|
|
@@ -54,6 +64,7 @@ def _close_position(position, dry_run: bool = False) -> bool:
|
|
|
54
64
|
"type_filling": mt5.ORDER_FILLING_IOC,
|
|
55
65
|
}
|
|
56
66
|
|
|
67
|
+
# Conta hedge → precisa do ticket
|
|
57
68
|
if position.ticket:
|
|
58
69
|
request["position"] = position.ticket
|
|
59
70
|
|
|
@@ -65,13 +76,15 @@ def _close_position(position, dry_run: bool = False) -> bool:
|
|
|
65
76
|
|
|
66
77
|
if not result:
|
|
67
78
|
log.error(
|
|
68
|
-
f"[PANIC] order_send None |
|
|
79
|
+
f"[PANIC] order_send retornou None | "
|
|
80
|
+
f"{symbol} | last_error={mt5.last_error()}"
|
|
69
81
|
)
|
|
70
82
|
return False
|
|
71
83
|
|
|
72
84
|
if result.retcode != mt5.TRADE_RETCODE_DONE:
|
|
73
85
|
log.error(
|
|
74
|
-
f"[PANIC] Falha ao fechar {symbol} |
|
|
86
|
+
f"[PANIC] Falha ao fechar posição {symbol} | "
|
|
87
|
+
f"retcode={result.retcode}"
|
|
75
88
|
)
|
|
76
89
|
return False
|
|
77
90
|
|
|
@@ -87,13 +100,21 @@ def panic_close_all(
|
|
|
87
100
|
dry_run: bool = False,
|
|
88
101
|
) -> dict:
|
|
89
102
|
"""
|
|
90
|
-
Executa o fechamento emergencial de posições e ordens.
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
103
|
+
Executa o fechamento emergencial de TODAS as posições e ordens.
|
|
104
|
+
|
|
105
|
+
Parâmetros
|
|
106
|
+
----------
|
|
107
|
+
retry_on_market_open : bool
|
|
108
|
+
Reexecuta automaticamente quando o market estiver fechado.
|
|
109
|
+
retry_interval : int
|
|
110
|
+
Intervalo (segundos) entre tentativas quando market fechado.
|
|
111
|
+
dry_run : bool
|
|
112
|
+
Simula as ações sem enviar ordens reais.
|
|
113
|
+
|
|
114
|
+
Retorna
|
|
115
|
+
-------
|
|
116
|
+
dict
|
|
117
|
+
Estatísticas da execução do panic close.
|
|
97
118
|
"""
|
|
98
119
|
stats = {
|
|
99
120
|
"positions_total": 0,
|
|
@@ -105,6 +126,8 @@ def panic_close_all(
|
|
|
105
126
|
}
|
|
106
127
|
|
|
107
128
|
while True:
|
|
129
|
+
market_fechado = False
|
|
130
|
+
|
|
108
131
|
with mt5_conexao():
|
|
109
132
|
if not _trade_permitido():
|
|
110
133
|
log.critical("[PANIC] Trading desabilitado na conta!")
|
|
@@ -117,9 +140,7 @@ def panic_close_all(
|
|
|
117
140
|
if positions:
|
|
118
141
|
stats["positions_total"] = len(positions)
|
|
119
142
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
# 1️⃣ Fechar posições
|
|
143
|
+
# 1️⃣ Fechamento de posições
|
|
123
144
|
if positions:
|
|
124
145
|
for pos in positions:
|
|
125
146
|
if not _market_aberto(pos.symbol):
|
|
@@ -132,25 +153,40 @@ def panic_close_all(
|
|
|
132
153
|
if _close_position(pos, dry_run=dry_run):
|
|
133
154
|
stats["positions_closed"] += 1
|
|
134
155
|
|
|
135
|
-
# 2️⃣
|
|
156
|
+
# 2️⃣ Cancelamento de ordens pendentes
|
|
136
157
|
if orders:
|
|
137
158
|
for ordem in orders:
|
|
138
159
|
if dry_run:
|
|
139
160
|
log.warning(
|
|
140
|
-
f"[PANIC][DRY] Cancelamento simulado |
|
|
161
|
+
f"[PANIC][DRY] Cancelamento simulado | "
|
|
162
|
+
f"ticket={ordem.ticket}"
|
|
141
163
|
)
|
|
142
164
|
stats["orders_cancelled"] += 1
|
|
143
165
|
continue
|
|
144
166
|
|
|
145
|
-
|
|
146
|
-
|
|
167
|
+
request = {
|
|
168
|
+
"action": mt5.TRADE_ACTION_REMOVE,
|
|
169
|
+
"order": ordem.ticket,
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
result = mt5.order_send(request)
|
|
173
|
+
|
|
174
|
+
if not result:
|
|
175
|
+
log.error(
|
|
176
|
+
f"[PANIC] Falha ao cancelar ordem {ordem.ticket} | "
|
|
177
|
+
f"last_error={mt5.last_error()}"
|
|
178
|
+
)
|
|
179
|
+
continue
|
|
180
|
+
|
|
181
|
+
if result.retcode == mt5.TRADE_RETCODE_DONE:
|
|
147
182
|
stats["orders_cancelled"] += 1
|
|
148
183
|
log.warning(
|
|
149
184
|
f"[PANIC] Ordem cancelada | ticket={ordem.ticket}"
|
|
150
185
|
)
|
|
151
186
|
else:
|
|
152
187
|
log.error(
|
|
153
|
-
f"[PANIC] Falha ao cancelar ordem {ordem.ticket}"
|
|
188
|
+
f"[PANIC] Falha ao cancelar ordem {ordem.ticket} | "
|
|
189
|
+
f"retcode={result.retcode}"
|
|
154
190
|
)
|
|
155
191
|
|
|
156
192
|
if not market_fechado:
|
|
@@ -162,7 +198,7 @@ def panic_close_all(
|
|
|
162
198
|
break
|
|
163
199
|
|
|
164
200
|
log.critical(
|
|
165
|
-
f"[PANIC] Market fechado.
|
|
201
|
+
f"[PANIC] Market fechado. Nova tentativa em {retry_interval}s..."
|
|
166
202
|
)
|
|
167
203
|
time.sleep(retry_interval)
|
|
168
204
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|