mtcli-risco 2.0.0__tar.gz → 2.1.1__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.
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: mtcli-risco
3
- Version: 2.0.0
4
- Summary: Plugin do mtcli
3
+ Version: 2.1.1
4
+ Summary: Plugin mtcli para controle de loss diário
5
5
  License: GPL-3.0
6
6
  Author: Valmir França da Silva
7
7
  Author-email: vfranca3@gmail.com
@@ -20,9 +20,11 @@ Project-URL: issues, https://github.com/vfranca/mtcli-risco/issues
20
20
  Description-Content-Type: text/markdown
21
21
 
22
22
  # mtcli-risco
23
+
24
+ ![Testes](https://github.com/vfranca/mtcli-risco/actions/workflows/tests.yml/badge.svg)
23
25
 
24
26
  Plugin para controle de risco diário integrado ao mtcli. Bloqueia automaticamente o envio de ordens caso o limite de prejuízo do dia seja ultrapassado.
25
-
27
+
26
28
  ---
27
29
 
28
30
  ## Instalação
@@ -1,7 +1,9 @@
1
1
  # mtcli-risco
2
+
3
+ ![Testes](https://github.com/vfranca/mtcli-risco/actions/workflows/tests.yml/badge.svg)
2
4
 
3
5
  Plugin para controle de risco diário integrado ao mtcli. Bloqueia automaticamente o envio de ordens caso o limite de prejuízo do dia seja ultrapassado.
4
-
6
+
5
7
  ---
6
8
 
7
9
  ## Instalação
@@ -0,0 +1,2 @@
1
+ from .checar import checar
2
+ from .monitorar import monitorar
@@ -1,73 +1,67 @@
1
- """Comando checar - verifica se o loss limit foi atingido."""
2
-
3
- import click
4
- from datetime import date
5
- from mtcli.conecta import conectar, shutdown
6
- from mtcli.logger import setup_logger
7
- from .conf import LOSS_LIMIT, STATUS_FILE
8
- from .risco import (
9
- carregar_estado,
10
- salvar_estado,
11
- risco_excedido,
12
- encerrar_todas_posicoes,
13
- cancelar_todas_ordens,
14
- calcular_lucro_total_dia,
15
- )
16
-
17
-
18
- log = setup_logger()
19
-
20
-
21
- @click.command("checar")
22
- @click.option(
23
- "--limite",
24
- "-l",
25
- default=LOSS_LIMIT,
26
- help="Limite de perda diária (ex: -500), default -180.00.",
27
- )
28
- @click.option(
29
- "--lucro",
30
- is_flag=True,
31
- default=False,
32
- help="Exibe o lucro total do dia atualizado e sai.",
33
- )
34
- def checar(limite, lucro):
35
- """Verifica e bloqueia ordens se o limite de prejuízo for atingido."""
36
- conectar()
37
-
38
- if lucro:
39
- lucro = calcular_lucro_total_dia()
40
- click.echo(f"Lucro total do dia: {lucro:.2f}")
41
- log.info(f"Lucro total do dia: {lucro:.2f}")
42
- shutdown()
43
- return
44
-
45
- estado = carregar_estado(STATUS_FILE)
46
- hoje = date.today()
47
-
48
- if estado["data"] != hoje.isoformat():
49
- estado["bloqueado"] = False
50
-
51
- if estado["bloqueado"]:
52
- click.echo("Bloqueado hoje por risco. Nenhuma ordem deve ser enviada.")
53
- shutdown()
54
- return
55
-
56
- if risco_excedido(limite):
57
- click.echo(
58
- f"Limite {limite:.2f} excedido. Encerrando posições e bloqueando novas ordens."
59
- )
60
- log.info(f"Risco {limite:.2f} excedido, iniciando encerramento de posições.")
61
- encerrar_todas_posicoes()
62
- cancelar_todas_ordens()
63
- estado["bloqueado"] = True
64
- else:
65
- click.echo("Dentro do limite de risco.")
66
- log.info(f"Risco dentro do limite {limite:.2f}")
67
-
68
- salvar_estado(STATUS_FILE, hoje, estado["bloqueado"])
69
- shutdown()
70
-
71
-
72
- if __name__ == "__main__":
73
- checar()
1
+ """Comando checar - verifica se o loss limit foi atingido."""
2
+
3
+ import click
4
+ from datetime import date
5
+ from mtcli.logger import setup_logger
6
+ from ..conf import LOSS_LIMIT, STATUS_FILE
7
+ from ..models.lucro import calcular_lucro_total_dia
8
+ from ..models.risco import (
9
+ carregar_estado,
10
+ salvar_estado,
11
+ risco_excedido,
12
+ encerrar_todas_posicoes,
13
+ cancelar_todas_ordens,
14
+ )
15
+
16
+
17
+ log = setup_logger()
18
+
19
+
20
+ @click.command("checar")
21
+ @click.option(
22
+ "--limite",
23
+ "-l",
24
+ default=LOSS_LIMIT,
25
+ help="Limite de perda diária (ex: -500), default -180.00.",
26
+ )
27
+ @click.option(
28
+ "--lucro",
29
+ is_flag=True,
30
+ default=False,
31
+ help="Exibe o lucro total do dia atualizado e sai.",
32
+ )
33
+ def checar(limite, lucro):
34
+ """Verifica e bloqueia ordens se o limite de prejuízo for atingido."""
35
+ if lucro:
36
+ lucro = calcular_lucro_total_dia()
37
+ click.echo(f"Lucro total do dia: {lucro:.2f}")
38
+ log.info(f"Lucro total do dia: {lucro:.2f}")
39
+ return
40
+
41
+ estado = carregar_estado(STATUS_FILE)
42
+ hoje = date.today()
43
+
44
+ if estado["data"] != hoje.isoformat():
45
+ estado["bloqueado"] = False
46
+
47
+ if estado["bloqueado"]:
48
+ click.echo("Bloqueado hoje por risco. Nenhuma ordem deve ser enviada.")
49
+ return
50
+
51
+ if risco_excedido(limite):
52
+ click.echo(
53
+ f"Limite {limite:.2f} excedido. Encerrando posições e bloqueando novas ordens."
54
+ )
55
+ log.info(f"Risco {limite:.2f} excedido, iniciando encerramento de posições.")
56
+ encerrar_todas_posicoes()
57
+ cancelar_todas_ordens()
58
+ estado["bloqueado"] = True
59
+ else:
60
+ click.echo("Dentro do limite de risco.")
61
+ log.info(f"Risco dentro do limite {limite:.2f}")
62
+
63
+ salvar_estado(STATUS_FILE, hoje, estado["bloqueado"])
64
+
65
+
66
+ if __name__ == "__main__":
67
+ checar()
@@ -0,0 +1,53 @@
1
+ """Comando lucro - exibe os diferentes tipos de lucro."""
2
+
3
+ import click
4
+ from mtcli.logger import setup_logger
5
+ from ..models.lucro import (
6
+ obter_lucro_aberto,
7
+ calcular_lucro_realizado,
8
+ calcular_lucro_total_dia,
9
+ )
10
+
11
+
12
+ log = setup_logger()
13
+
14
+
15
+ @click.command("lucro")
16
+ @click.option(
17
+ "--aberto", "-a", is_flag=True, default=False, help="Exibe o lucro aberto."
18
+ )
19
+ @click.option(
20
+ "--realizado",
21
+ "-r",
22
+ is_flag=True,
23
+ default=False,
24
+ help="Exibe o lucro realizado do dia.",
25
+ )
26
+ @click.option(
27
+ "--total", "-t", is_flag=True, default=False, help="Exibe o lucro total do dia."
28
+ )
29
+ def lucro(aberto, realizado, total):
30
+ """Exibe os lucros aberto, realizado e total do dia."""
31
+ lucro_aberto = obter_lucro_aberto()
32
+ lucro_realizado = calcular_lucro_realizado()
33
+ lucro_total = calcular_lucro_total_dia()
34
+
35
+ if aberto:
36
+ click.echo(f"{lucro_aberto:.2f}")
37
+ return
38
+
39
+ if realizado:
40
+ click.echo(f"{lucro_realizado:.2f}")
41
+ return
42
+
43
+ if total:
44
+ click.echo(f"{lucro_total:.2f}")
45
+ return
46
+
47
+ click.echo(f"lucro em aberto {lucro_aberto:.2f}")
48
+ click.echo(f"lucro realizado {lucro_realizado:.2f}")
49
+ click.echo(f"lucro total {lucro_total:.2f}")
50
+
51
+
52
+ if __name__ == "__main__":
53
+ lucro()
@@ -1,58 +1,56 @@
1
- """Comando monitorar - monitora o prejuízo do dia."""
2
-
3
- import time
4
- import click
5
- from datetime import date
6
- from mtcli.conecta import conectar, shutdown
7
- from mtcli.logger import setup_logger
8
- from .conf import LOSS_LIMIT, STATUS_FILE, INTERVALO
9
- from .risco import (
10
- carregar_estado,
11
- salvar_estado,
12
- risco_excedido,
13
- encerrar_todas_posicoes,
14
- cancelar_todas_ordens,
15
- )
16
-
17
- log = setup_logger()
18
-
19
-
20
- @click.command("monitorar")
21
- @click.option("--limite", "-l", default=LOSS_LIMIT, help="Limite de perda diária.")
22
- @click.option(
23
- "--intervalo", "-i", default=INTERVALO, help="Intervalo entre verificações (segundos) default 60."
24
- )
25
- def monitorar(limite, intervalo):
26
- """Monitora continuamente o risco em tempo real."""
27
- conectar()
28
- click.echo(f"Monitorando risco a cada {intervalo}s. Limite: {limite}")
29
- try:
30
- while True:
31
- hoje = date.today()
32
- estado = carregar_estado(STATUS_FILE)
33
-
34
- if estado.get("data") != hoje.isoformat():
35
- estado["bloqueado"] = False
36
- salvar_estado(STATUS_FILE, hoje, False)
37
-
38
- if not estado.get("bloqueado") and risco_excedido(limite):
39
- click.echo("Limite {limite} excedido. Encerrando posições.")
40
- encerrar_todas_posicoes()
41
- cancelar_todas_ordens()
42
- salvar_estado(STATUS_FILE, hoje, True)
43
- elif estado.get("bloqueado"):
44
- click.echo(f"O limite {limite} foi excedido")
45
- shutdown()
46
- return
47
- else:
48
- click.echo(f"Dentro do limite {limite}")
49
-
50
- time.sleep(intervalo)
51
- except KeyboardInterrupt:
52
- click.echo("Monitoramento interrompido.")
53
- finally:
54
- shutdown()
55
-
56
-
57
- if __name__ == "__main__":
58
- monitorar()
1
+ """Comando monitorar - monitora o prejuízo do dia."""
2
+
3
+ import time
4
+ import click
5
+ from datetime import date
6
+ from mtcli.logger import setup_logger
7
+ from ..conf import LOSS_LIMIT, STATUS_FILE, INTERVALO
8
+ from ..models.risco import (
9
+ carregar_estado,
10
+ salvar_estado,
11
+ risco_excedido,
12
+ encerrar_todas_posicoes,
13
+ cancelar_todas_ordens,
14
+ )
15
+
16
+ log = setup_logger()
17
+
18
+
19
+ @click.command("monitorar")
20
+ @click.option("--limite", "-l", default=LOSS_LIMIT, help="Limite de perda diária.")
21
+ @click.option(
22
+ "--intervalo",
23
+ "-i",
24
+ default=INTERVALO,
25
+ help="Intervalo entre verificações (segundos), default 60.",
26
+ )
27
+ def monitorar(limite, intervalo):
28
+ """Monitora continuamente o risco em tempo real."""
29
+ click.echo(f"Monitorando risco a cada {intervalo}s. Limite: {limite}")
30
+ try:
31
+ while True:
32
+ hoje = date.today()
33
+ estado = carregar_estado(STATUS_FILE)
34
+
35
+ if estado.get("data") != hoje.isoformat():
36
+ estado["bloqueado"] = False
37
+ salvar_estado(STATUS_FILE, hoje, False)
38
+
39
+ if not estado.get("bloqueado") and risco_excedido(limite):
40
+ click.echo(f"Limite {limite} excedido. Encerrando posições.")
41
+ log.info(f"Risco excedido em {limite}. Encerrando posições.")
42
+ encerrar_todas_posicoes()
43
+ cancelar_todas_ordens()
44
+ salvar_estado(STATUS_FILE, hoje, True)
45
+ elif estado.get("bloqueado"):
46
+ click.echo(f"O limite {limite} foi excedido. Sistema bloqueado hoje.")
47
+ else:
48
+ click.echo(f"Dentro do limite {limite}")
49
+
50
+ time.sleep(intervalo)
51
+ except KeyboardInterrupt:
52
+ click.echo("Monitoramento interrompido.")
53
+
54
+
55
+ if __name__ == "__main__":
56
+ monitorar()
@@ -1,13 +1,15 @@
1
- import os
2
- from mtcli.conf import config
3
-
4
-
5
- LOSS_LIMIT = float(
6
- os.getenv("LOSS_LIMIT", config["DEFAULT"].getfloat("loss_limit", fallback=-180.00))
7
- )
8
-
9
- STATUS_FILE = os.getenv(
10
- "STATUS_FILE",
11
- config["DEFAULT"].get("status_file", fallback="bloqueio.json"),
12
- )
13
- INTERVALO = int(os.getenv("INTERVALO", config["DEFAULT"].getint("intervalo", fallback=60)))
1
+ import os
2
+ from mtcli.conf import config
3
+
4
+
5
+ LOSS_LIMIT = float(
6
+ os.getenv("LOSS_LIMIT", config["DEFAULT"].getfloat("loss_limit", fallback=-180.00))
7
+ )
8
+
9
+ STATUS_FILE = os.getenv(
10
+ "STATUS_FILE",
11
+ config["DEFAULT"].get("status_file", fallback="bloqueio.json"),
12
+ )
13
+ INTERVALO = int(
14
+ os.getenv("INTERVALO", config["DEFAULT"].getint("intervalo", fallback=60))
15
+ )
File without changes
@@ -0,0 +1,58 @@
1
+ """Cálculos do lucro do dia."""
2
+
3
+ import MetaTrader5 as mt5
4
+ from datetime import date, datetime, time
5
+ from mtcli.conecta import conectar, shutdown
6
+ from mtcli.logger import setup_logger
7
+ from ..mt5_context import mt5_conexao
8
+
9
+
10
+ log = setup_logger()
11
+
12
+
13
+ def calcular_lucro_realizado() -> float:
14
+ """Calcula o lucro realizado do dia."""
15
+ hoje = datetime.now().date()
16
+ inicio = datetime.combine(hoje, time(0, 0))
17
+ fim = datetime.combine(hoje, time(23, 59))
18
+
19
+ with mt5_conexao():
20
+ deals = mt5.history_deals_get(inicio, fim)
21
+ log.debug(f"Deals recebidos: {deals}")
22
+ log.debug(f"Tipo de deals: {type(deals)}")
23
+
24
+ lucro_realizado = 0.0
25
+
26
+ if deals is None:
27
+ log.warning("Nenhum deal retornado.")
28
+ return 0.0
29
+
30
+ if not isinstance(deals, (list, tuple)):
31
+ deals = [deals]
32
+
33
+ lucro_realizado = sum(deal.profit for deal in deals if deal.type in (1, 2))
34
+ log.info(f"lucro realizado: {lucro_realizado:.2f}")
35
+
36
+ return lucro_realizado
37
+
38
+
39
+ def obter_lucro_aberto() -> float:
40
+ """Obtem o lucro em aberto."""
41
+ with mt5_conexao():
42
+ info = mt5.account_info()
43
+
44
+ lucro_aberto = info.profit if info else 0.0
45
+ log.info(f"lucro aberto: {lucro_aberto:.2f}")
46
+
47
+ return lucro_aberto
48
+
49
+
50
+ def calcular_lucro_total_dia() -> float:
51
+ """Calcula o lucro total do dia."""
52
+ realizado = calcular_lucro_realizado()
53
+ aberto = obter_lucro_aberto()
54
+ total = realizado + aberto
55
+ log.info(
56
+ f"Lucro realizado: {realizado:.2f}, lucro aberto: {aberto:.2f}, total: {total:.2f}"
57
+ )
58
+ return total
@@ -0,0 +1,94 @@
1
+ """Lógica do plugin risco."""
2
+
3
+ import MetaTrader5 as mt5
4
+ import json
5
+ import os
6
+ from datetime import date, datetime, time
7
+ from mtcli.logger import setup_logger
8
+ from .lucro import calcular_lucro_total_dia
9
+ from ..mt5_context import mt5_conexao
10
+
11
+
12
+ log = setup_logger()
13
+
14
+
15
+ def carregar_estado(STATUS_FILE):
16
+ """Carrega o estado do controle de risco."""
17
+ if os.path.exists(STATUS_FILE):
18
+ with open(STATUS_FILE, "r") as f:
19
+ log.info(f"Carregando dados do arquivo {STATUS_FILE}")
20
+ return json.load(f)
21
+ return {"data": None, "bloqueado": False}
22
+
23
+
24
+ def salvar_estado(STATUS_FILE, data, bloqueado):
25
+ """Salva o estado do controle de risco."""
26
+ with open(STATUS_FILE, "w") as f:
27
+ json.dump({"data": data.isoformat(), "bloqueado": bloqueado}, f)
28
+ log.info(f"Salvando o estado: data {data} bloqueado {bloqueado}")
29
+
30
+
31
+ def encerrar_todas_posicoes():
32
+ """Encerra todas as posições abertas."""
33
+ with mt5_conexao():
34
+ positions = mt5.positions_get()
35
+ if not positions:
36
+ log.info("Nenhuma posição aberta para fechar.")
37
+ return
38
+
39
+ with mt5_conexao():
40
+ for pos in positions:
41
+ tipo_oposto = (
42
+ mt5.ORDER_TYPE_SELL
43
+ if pos.type == mt5.ORDER_TYPE_BUY
44
+ else mt5.ORDER_TYPE_BUY
45
+ )
46
+ ordem_fechar = {
47
+ "action": mt5.TRADE_ACTION_DEAL,
48
+ "symbol": pos.symbol,
49
+ "volume": pos.volume,
50
+ "type": tipo_oposto,
51
+ "position": pos.ticket,
52
+ "deviation": 10,
53
+ "magic": 1000,
54
+ "comment": "Fechando posição por limite de risco",
55
+ }
56
+ resultado = mt5.order_send(ordem_fechar)
57
+ if resultado.retcode != mt5.TRADE_RETCODE_DONE:
58
+ log.error(f"Falha ao fechar posição {pos.ticket}: {resultado.retcode}")
59
+ else:
60
+ log.info(f"Posição {pos.ticket} fechada com sucesso.")
61
+
62
+
63
+ def cancelar_todas_ordens():
64
+ """Cancela todas órdens pendentes."""
65
+ with mt5_conexao():
66
+ ordens = mt5.orders_get()
67
+ if not ordens:
68
+ log.info("Nenhuma ordem pendente para cancelar.")
69
+ return
70
+
71
+ with mt5_conexao():
72
+ for ordem in ordens:
73
+ resultado = mt5.order_delete(ordem.ticket)
74
+ if resultado.retcode != mt5.TRADE_RETCODE_DONE:
75
+ log.error(
76
+ f"Falha ao cancelar ordem {ordem.ticket}: {resultado.retcode}"
77
+ )
78
+ else:
79
+ log.info(f"Ordem {ordem.ticket} cancelada com sucesso.")
80
+
81
+
82
+ def risco_excedido(limite):
83
+ """Verifica se o loss limit do dia foi atingido."""
84
+ try:
85
+ total_lucro = calcular_lucro_total_dia()
86
+ if total_lucro <= limite:
87
+ log.info(
88
+ f"Limite de prejuízo excedido! prejuízo: {total_lucro:.2f}, limite: {limite:.2f}"
89
+ )
90
+ return True
91
+ return False
92
+ except Exception as e:
93
+ log.error(f"Erro ao verificar risco: {e}")
94
+ return False
@@ -0,0 +1,11 @@
1
+ from contextlib import contextmanager
2
+ from mtcli.conecta import conectar, shutdown
3
+
4
+
5
+ @contextmanager
6
+ def mt5_conexao():
7
+ conectar()
8
+ try:
9
+ yield
10
+ finally:
11
+ shutdown()
@@ -1,20 +1,22 @@
1
- """Comando risco adiciona risco ao mtcli."""
2
-
3
- import click
4
- from .checar import checar
5
- from .monitorar import monitorar
6
-
7
-
8
- @click.group("risco")
9
- @click.version_option(package_name="mtcli-risco")
10
- def cli():
11
- """Monitora e bloqueia ordens se o limite de prejuízo for atingido."""
12
- pass
13
-
14
-
15
- cli.add_command(checar)
16
- cli.add_command(monitorar)
17
-
18
-
19
- if __name__ == "__main__":
20
- cli()
1
+ """Comando risco: monitora e bloqueia ordens se o limite diário de prejuízo for atingido."""
2
+
3
+ import click
4
+ from .commands.checar import checar
5
+ from .commands.monitorar import monitorar
6
+ from .commands.lucro import lucro
7
+
8
+
9
+ @click.group("risco")
10
+ @click.version_option(package_name="mtcli-risco")
11
+ def cli():
12
+ """Monitora e bloqueia ordens se o limite de prejuízo for atingido."""
13
+ pass
14
+
15
+
16
+ cli.add_command(checar)
17
+ cli.add_command(monitorar)
18
+ cli.add_command(lucro)
19
+
20
+
21
+ if __name__ == "__main__":
22
+ cli()
@@ -1,7 +1,7 @@
1
1
  [project]
2
2
  name = "mtcli-risco"
3
- version = "2.0.0"
4
- description = "Plugin do mtcli"
3
+ version = "2.1.1"
4
+ description = "Plugin mtcli para controle de loss diário"
5
5
  authors = [
6
6
  {name = "Valmir França da Silva",email = "vfranca3@gmail.com"}
7
7
  ]
@@ -19,7 +19,7 @@ repository = "https://github.com/vfranca/mtcli-risco"
19
19
  issues = "https://github.com/vfranca/mtcli-risco/issues"
20
20
 
21
21
  [project.entry-points."mtcli.plugins"]
22
- risco = "mtcli_risco.plugin:cli"
22
+ mtcli-risco = "mtcli_risco.plugin:cli"
23
23
 
24
24
  [build-system]
25
25
  requires = ["poetry-core>=2.0.0,<3.0.0"]
@@ -1,110 +0,0 @@
1
- """Lógica do plugin risco."""
2
-
3
- import MetaTrader5 as mt5
4
- import json
5
- import os
6
- from datetime import date, datetime, time
7
- from mtcli.conecta import conectar, shutdown
8
- from mtcli.logger import setup_logger
9
-
10
- log = setup_logger()
11
-
12
-
13
- def carregar_estado(STATUS_FILE):
14
- """Carrega o estado do controle de risco."""
15
- if os.path.exists(STATUS_FILE):
16
- with open(STATUS_FILE, "r") as f:
17
- log.info(f"Carregando dados do arquivo {STATUS_FILE}")
18
- return json.load(f)
19
- return {"data": None, "bloqueado": False}
20
-
21
-
22
- def salvar_estado(STATUS_FILE, data, bloqueado):
23
- """Salva o estado do controle de risco."""
24
- with open(STATUS_FILE, "w") as f:
25
- json.dump({"data": data.isoformat(), "bloqueado": bloqueado}, f)
26
- log.info(f"Salvando o estado: data {data} bloqueado {bloqueado}")
27
-
28
-
29
- def calcular_lucro_total_dia():
30
- """Calcula o lucro total do dia."""
31
- hoje = datetime.now().date()
32
- inicio = datetime.combine(hoje, time(0, 0))
33
- fim = datetime.combine(hoje, time(23, 59))
34
-
35
- deals = mt5.history_deals_get(inicio, fim)
36
- lucro_realizado = 0.0
37
-
38
- if deals is not None:
39
- lucro_realizado = sum(deal.profit for deal in deals if deal.type in (1, 2))
40
-
41
- info = mt5.account_info()
42
- lucro_aberto = info.profit if info else 0.0
43
-
44
- total = lucro_realizado + lucro_aberto
45
- log.info(
46
- f"Lucro realizado: {lucro_realizado}, lucro aberto: {lucro_aberto}, total: {total}"
47
- )
48
- return total
49
-
50
-
51
- def encerrar_todas_posicoes():
52
- positions = mt5.positions_get()
53
- if not positions:
54
- log.info("Nenhuma posição aberta para fechar.")
55
- return
56
-
57
- for pos in positions:
58
- tipo_oposto = (
59
- mt5.ORDER_TYPE_SELL
60
- if pos.type == mt5.ORDER_TYPE_BUY
61
- else mt5.ORDER_TYPE_BUY
62
- )
63
- ordem_fechar = {
64
- "action": mt5.TRADE_ACTION_DEAL,
65
- "symbol": pos.symbol,
66
- "volume": pos.volume,
67
- "type": tipo_oposto,
68
- "position": pos.ticket,
69
- "deviation": 10,
70
- "magic": 1000,
71
- "comment": "Fechando posição por limite de risco",
72
- }
73
- resultado = mt5.order_send(ordem_fechar)
74
- if resultado.retcode != mt5.TRADE_RETCODE_DONE:
75
- log.error(f"Falha ao fechar posição {pos.ticket}: {resultado.retcode}")
76
- else:
77
- log.info(f"Posição {pos.ticket} fechada com sucesso.")
78
-
79
-
80
- def cancelar_todas_ordens():
81
- ordens = mt5.orders_get()
82
- if not ordens:
83
- log.info("Nenhuma ordem pendente para cancelar.")
84
- return
85
-
86
- for ordem in ordens:
87
- resultado = mt5.order_delete(ordem.ticket)
88
- if resultado.retcode != mt5.TRADE_RETCODE_DONE:
89
- log.error(f"Falha ao cancelar ordem {ordem.ticket}: {resultado.retcode}")
90
- else:
91
- log.info(f"Ordem {ordem.ticket} cancelada com sucesso.")
92
-
93
-
94
- def risco_excedido(limite):
95
- conectar()
96
- try:
97
- total_lucro = calcular_lucro_total_dia()
98
- if total_lucro <= limite:
99
- log.warning(
100
- "Limite de prejuízo excedido! Encerrando posições e cancelando ordens."
101
- )
102
- encerrar_todas_posicoes()
103
- cancelar_todas_ordens()
104
- return True
105
- return False
106
- except Exception as e:
107
- log.error(f"Erro ao verificar risco: {e}")
108
- return False
109
- finally:
110
- shutdown()
File without changes