mtcli 3.2.0.dev2__tar.gz → 3.2.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.
Files changed (69) hide show
  1. {mtcli-3.2.0.dev2 → mtcli-3.2.1}/PKG-INFO +1 -1
  2. {mtcli-3.2.0.dev2 → mtcli-3.2.1}/mtcli/commands/bars.py +42 -13
  3. {mtcli-3.2.0.dev2 → mtcli-3.2.1}/mtcli/conecta.py +41 -41
  4. {mtcli-3.2.0.dev2 → mtcli-3.2.1}/mtcli/conf.py +101 -101
  5. {mtcli-3.2.0.dev2 → mtcli-3.2.1}/mtcli/data/mt5.py +97 -97
  6. {mtcli-3.2.0.dev2 → mtcli-3.2.1}/mtcli/logger.py +45 -45
  7. {mtcli-3.2.0.dev2 → mtcli-3.2.1}/mtcli/mt5_context.py +33 -33
  8. {mtcli-3.2.0.dev2 → mtcli-3.2.1}/pyproject.toml +1 -1
  9. {mtcli-3.2.0.dev2 → mtcli-3.2.1}/LICENSE +0 -0
  10. {mtcli-3.2.0.dev2 → mtcli-3.2.1}/README.md +0 -0
  11. {mtcli-3.2.0.dev2 → mtcli-3.2.1}/mtcli/__init__.py +0 -0
  12. {mtcli-3.2.0.dev2 → mtcli-3.2.1}/mtcli/commands/__init__.py +0 -0
  13. {mtcli-3.2.0.dev2 → mtcli-3.2.1}/mtcli/commands/conf.py +0 -0
  14. {mtcli-3.2.0.dev2 → mtcli-3.2.1}/mtcli/commands/logs.py +0 -0
  15. {mtcli-3.2.0.dev2 → mtcli-3.2.1}/mtcli/data/__init__.py +0 -0
  16. {mtcli-3.2.0.dev2 → mtcli-3.2.1}/mtcli/data/base.py +0 -0
  17. {mtcli-3.2.0.dev2 → mtcli-3.2.1}/mtcli/data/csv.py +0 -0
  18. {mtcli-3.2.0.dev2 → mtcli-3.2.1}/mtcli/models/__init__.py +0 -0
  19. {mtcli-3.2.0.dev2 → mtcli-3.2.1}/mtcli/models/bar_model.py +0 -0
  20. {mtcli-3.2.0.dev2 → mtcli-3.2.1}/mtcli/models/bars_model.py +0 -0
  21. {mtcli-3.2.0.dev2 → mtcli-3.2.1}/mtcli/models/chart_model.py +0 -0
  22. {mtcli-3.2.0.dev2 → mtcli-3.2.1}/mtcli/models/conf_model.py +0 -0
  23. {mtcli-3.2.0.dev2 → mtcli-3.2.1}/mtcli/models/consecutive_bars_model.py +0 -0
  24. {mtcli-3.2.0.dev2 → mtcli-3.2.1}/mtcli/models/rates_model.py +0 -0
  25. {mtcli-3.2.0.dev2 → mtcli-3.2.1}/mtcli/models/signals_model.py +0 -0
  26. {mtcli-3.2.0.dev2 → mtcli-3.2.1}/mtcli/models/unconsecutive_bar_model.py +0 -0
  27. {mtcli-3.2.0.dev2 → mtcli-3.2.1}/mtcli/mt.py +0 -0
  28. {mtcli-3.2.0.dev2 → mtcli-3.2.1}/mtcli/plugin.py +0 -0
  29. {mtcli-3.2.0.dev2 → mtcli-3.2.1}/mtcli/plugins/__init__.py +0 -0
  30. {mtcli-3.2.0.dev2 → mtcli-3.2.1}/mtcli/plugins/agressao/__init__.py +0 -0
  31. {mtcli-3.2.0.dev2 → mtcli-3.2.1}/mtcli/plugins/agressao/command.py +0 -0
  32. {mtcli-3.2.0.dev2 → mtcli-3.2.1}/mtcli/plugins/agressao/conf.py +0 -0
  33. {mtcli-3.2.0.dev2 → mtcli-3.2.1}/mtcli/plugins/agressao/models/__init__.py +0 -0
  34. {mtcli-3.2.0.dev2 → mtcli-3.2.1}/mtcli/plugins/agressao/models/model_agressao.py +0 -0
  35. {mtcli-3.2.0.dev2 → mtcli-3.2.1}/mtcli/plugins/agressao/views/__init__.py +0 -0
  36. {mtcli-3.2.0.dev2 → mtcli-3.2.1}/mtcli/plugins/agressao/views/view_agressao.py +0 -0
  37. {mtcli-3.2.0.dev2 → mtcli-3.2.1}/mtcli/plugins/media_movel/__init__.py +0 -0
  38. {mtcli-3.2.0.dev2 → mtcli-3.2.1}/mtcli/plugins/media_movel/command.py +0 -0
  39. {mtcli-3.2.0.dev2 → mtcli-3.2.1}/mtcli/plugins/media_movel/conf.py +0 -0
  40. {mtcli-3.2.0.dev2 → mtcli-3.2.1}/mtcli/plugins/media_movel/models/__init__.py +0 -0
  41. {mtcli-3.2.0.dev2 → mtcli-3.2.1}/mtcli/plugins/media_movel/models/model_media_movel.py +0 -0
  42. {mtcli-3.2.0.dev2 → mtcli-3.2.1}/mtcli/plugins/media_movel/tests/__init__.py +0 -0
  43. {mtcli-3.2.0.dev2 → mtcli-3.2.1}/mtcli/plugins/media_movel/tests/test_mm.py +0 -0
  44. {mtcli-3.2.0.dev2 → mtcli-3.2.1}/mtcli/plugins/media_movel/tests/test_model_media_movel.py +0 -0
  45. {mtcli-3.2.0.dev2 → mtcli-3.2.1}/mtcli/plugins/range_medio/__init__.py +0 -0
  46. {mtcli-3.2.0.dev2 → mtcli-3.2.1}/mtcli/plugins/range_medio/command.py +0 -0
  47. {mtcli-3.2.0.dev2 → mtcli-3.2.1}/mtcli/plugins/range_medio/conf.py +0 -0
  48. {mtcli-3.2.0.dev2 → mtcli-3.2.1}/mtcli/plugins/range_medio/models/__init__.py +0 -0
  49. {mtcli-3.2.0.dev2 → mtcli-3.2.1}/mtcli/plugins/range_medio/models/average_range_model.py +0 -0
  50. {mtcli-3.2.0.dev2 → mtcli-3.2.1}/mtcli/plugins/range_medio/tests/__init__.py +0 -0
  51. {mtcli-3.2.0.dev2 → mtcli-3.2.1}/mtcli/plugins/range_medio/tests/test_rm.py +0 -0
  52. {mtcli-3.2.0.dev2 → mtcli-3.2.1}/mtcli/plugins/volume_medio/__init__.py +0 -0
  53. {mtcli-3.2.0.dev2 → mtcli-3.2.1}/mtcli/plugins/volume_medio/command.py +0 -0
  54. {mtcli-3.2.0.dev2 → mtcli-3.2.1}/mtcli/plugins/volume_medio/conf.py +0 -0
  55. {mtcli-3.2.0.dev2 → mtcli-3.2.1}/mtcli/plugins/volume_medio/models/__init__.py +0 -0
  56. {mtcli-3.2.0.dev2 → mtcli-3.2.1}/mtcli/plugins/volume_medio/models/model_average_volume.py +0 -0
  57. {mtcli-3.2.0.dev2 → mtcli-3.2.1}/mtcli/plugins/volume_medio/tests/__init__.py +0 -0
  58. {mtcli-3.2.0.dev2 → mtcli-3.2.1}/mtcli/plugins/volume_medio/tests/test_vm.py +0 -0
  59. {mtcli-3.2.0.dev2 → mtcli-3.2.1}/mtcli/views/__init__.py +0 -0
  60. {mtcli-3.2.0.dev2 → mtcli-3.2.1}/mtcli/views/close_view.py +0 -0
  61. {mtcli-3.2.0.dev2 → mtcli-3.2.1}/mtcli/views/full_view.py +0 -0
  62. {mtcli-3.2.0.dev2 → mtcli-3.2.1}/mtcli/views/high_view.py +0 -0
  63. {mtcli-3.2.0.dev2 → mtcli-3.2.1}/mtcli/views/low_view.py +0 -0
  64. {mtcli-3.2.0.dev2 → mtcli-3.2.1}/mtcli/views/min_view.py +0 -0
  65. {mtcli-3.2.0.dev2 → mtcli-3.2.1}/mtcli/views/open_view.py +0 -0
  66. {mtcli-3.2.0.dev2 → mtcli-3.2.1}/mtcli/views/ranges_view.py +0 -0
  67. {mtcli-3.2.0.dev2 → mtcli-3.2.1}/mtcli/views/rates_view.py +0 -0
  68. {mtcli-3.2.0.dev2 → mtcli-3.2.1}/mtcli/views/vars_view.py +0 -0
  69. {mtcli-3.2.0.dev2 → mtcli-3.2.1}/mtcli/views/volumes_view.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: mtcli
3
- Version: 3.2.0.dev2
3
+ Version: 3.2.1
4
4
  Summary: Aplicativo CLI para exibir gráficos do MetaTrader 5 em texto acessível ao leitor de telas
5
5
  License: GPL-3.0
6
6
  Keywords: MetaTrader 5,trading,CLI
@@ -2,7 +2,6 @@
2
2
 
3
3
  import click
4
4
 
5
- from mtcli import conf
6
5
  from mtcli.models.rates_model import RatesModel
7
6
  from mtcli.models.bars_model import BarsModel
8
7
  from mtcli.views.full_view import FullView
@@ -15,6 +14,14 @@ from mtcli.views.open_view import OpenView
15
14
  from mtcli.views.high_view import HighView
16
15
  from mtcli.views.low_view import LowView
17
16
  from mtcli.views.close_view import CloseView
17
+ from mtcli.conf import (
18
+ VIEW,
19
+ PERIOD,
20
+ BARS,
21
+ DATE,
22
+ VOLUME,
23
+ TIMEFRAMES,
24
+ )
18
25
 
19
26
 
20
27
  @click.command(
@@ -51,34 +58,56 @@ from mtcli.views.close_view import CloseView
51
58
  ],
52
59
  case_sensitive=False,
53
60
  ),
54
- default=conf.view,
55
- help="Formato de exibicao, default m. Opcoes: ch ou m - minima; f - completa; r - ranges; v - volumes; va - variações percentuais; oh - OHLC; o - aberturas; h - maximas; l - minimas; c - fechamentos",
61
+ default=VIEW,
62
+ show_default=True,
63
+ help="Formato de exibicao. Opcoes: minima ou HL - minima; f - completa; r - ranges; v - volumes; va - variações percentuais; oh - OHLC; o - aberturas; h - maximas; l - minimas; c - fechamentos.",
56
64
  )
57
65
  @click.option(
58
66
  "--period",
59
67
  "-p",
60
- type=click.Choice(conf.timeframes, case_sensitive=False),
61
- default=conf.period,
62
- help="Tempo grafico, default D1.",
68
+ type=click.Choice(TIMEFRAMES, case_sensitive=False),
69
+ default=PERIOD,
70
+ show_default=True,
71
+ help="Timeframe das barras.",
63
72
  )
64
73
  @click.option(
65
74
  "--count",
66
75
  "-c",
67
76
  type=int,
68
- default=conf.periodos,
69
- help="Quantidade de barras, default 20.",
77
+ default=BARS,
78
+ show_default=True,
79
+ help="Numero de barras.",
80
+ )
81
+ @click.option(
82
+ "--date",
83
+ "-d",
84
+ default=DATE,
85
+ show_default=True,
86
+ help="Data para intraday, formato AAAA-MM-DD.",
87
+ )
88
+ @click.option(
89
+ "--numerator",
90
+ "-n",
91
+ is_flag=True,
92
+ default=False,
93
+ show_default=True,
94
+ help="Ativa a numeracao das barras.",
70
95
  )
71
96
  @click.option(
72
- "--date", "-d", default=conf.date, help="Data para intraday, formato AAAA-MM-DD."
97
+ "--show-date",
98
+ "-sd",
99
+ is_flag=True,
100
+ default=False,
101
+ show_default=True,
102
+ help="Ativa a datacao das barras.",
73
103
  )
74
- @click.option("--numerator", "-n", is_flag=True, help="Ativa a numeracao das barras.")
75
- @click.option("--show-date", "-sd", is_flag=True, help="Ativa a datacao das barras.")
76
104
  @click.option(
77
105
  "--volume",
78
106
  "-vo",
79
107
  type=click.Choice(["tick", "real"], case_sensitive=False),
80
- default=conf.volume,
81
- help="Tipo de volume, default tick.",
108
+ default=VOLUME,
109
+ show_default=True,
110
+ help="Tipo de volume.",
82
111
  )
83
112
  def bars(symbol, view, period, count, date, numerator, show_date, volume):
84
113
  """Exibe o grafico do MetaTrader 5."""
@@ -1,41 +1,41 @@
1
- """
2
- Gerencia a conexão direta com o terminal MetaTrader 5.
3
- Usado internamente pelo contexto mt5_conexao().
4
- """
5
-
6
- import MetaTrader5 as mt5
7
- from mtcli.logger import setup_logger
8
-
9
- log = setup_logger()
10
-
11
-
12
- def conectar() -> bool:
13
- """
14
- Inicializa a conexão com o MetaTrader 5.
15
-
16
- Retorna:
17
- bool: True se conectado com sucesso, False caso contrário.
18
-
19
- Levanta:
20
- ConnectionError: se a inicialização do MT5 falhar.
21
- """
22
- log.debug("Tentando inicializar conexao com MetaTrader 5...")
23
-
24
- if not mt5.initialize():
25
- erro = mt5.last_error()
26
- log.error(f"Erro ao conectar ao MetaTrader 5: {erro}")
27
- raise ConnectionError(f"Falha ao conectar ao MetaTrader 5: {erro}")
28
-
29
- log.info("Conexao com MetaTrader 5 estabelecida com sucesso.")
30
- return True
31
-
32
-
33
- def shutdown():
34
- """
35
- Encerra a conexão com o MetaTrader 5 de forma segura.
36
- """
37
- try:
38
- mt5.shutdown()
39
- log.debug("Conexao com MetaTrader 5 encerrada.")
40
- except Exception as e:
41
- log.error(f"Erro ao encerrar conexao com MetaTrader 5: {e}")
1
+ """
2
+ Gerencia a conexão direta com o terminal MetaTrader 5.
3
+ Usado internamente pelo contexto mt5_conexao().
4
+ """
5
+
6
+ import MetaTrader5 as mt5
7
+ from mtcli.logger import setup_logger
8
+
9
+ log = setup_logger()
10
+
11
+
12
+ def conectar() -> bool:
13
+ """
14
+ Inicializa a conexão com o MetaTrader 5.
15
+
16
+ Retorna:
17
+ bool: True se conectado com sucesso, False caso contrário.
18
+
19
+ Levanta:
20
+ ConnectionError: se a inicialização do MT5 falhar.
21
+ """
22
+ log.debug("Tentando inicializar conexao com MetaTrader 5...")
23
+
24
+ if not mt5.initialize():
25
+ erro = mt5.last_error()
26
+ log.error(f"Erro ao conectar ao MetaTrader 5: {erro}")
27
+ raise ConnectionError(f"Falha ao conectar ao MetaTrader 5: {erro}")
28
+
29
+ log.info("Conexao com MetaTrader 5 estabelecida com sucesso.")
30
+ return True
31
+
32
+
33
+ def shutdown():
34
+ """
35
+ Encerra a conexão com o MetaTrader 5 de forma segura.
36
+ """
37
+ try:
38
+ mt5.shutdown()
39
+ log.debug("Conexao com MetaTrader 5 encerrada.")
40
+ except Exception as e:
41
+ log.error(f"Erro ao encerrar conexao com MetaTrader 5: {e}")
@@ -1,101 +1,101 @@
1
- import os
2
- import MetaTrader5 as mt5
3
- from mtcli.conecta import conectar, shutdown
4
- from mtcli.models.conf_model import ConfModel
5
-
6
-
7
- config = ConfModel("mtcli.ini").carregar()
8
-
9
- section = "DEFAULT"
10
- symbol = os.getenv("SYMBOL", config[section].get("symbol", fallback="WIN$N"))
11
- digitos = int(os.getenv("DIGITOS", config[section].getint("digitos", fallback=2)))
12
- period = os.getenv("PERIOD", config[section].get("period", fallback="D1"))
13
- periodos = count = int(
14
- os.getenv("COUNT", config[section].getint("count", fallback=999))
15
- )
16
- view = os.getenv("VIEW", config[section].get("view", fallback="ch"))
17
- volume = os.getenv("VOLUME", config[section].get("volume", fallback="tick"))
18
- date = os.getenv("DATE", config[section].get("date", fallback=""))
19
-
20
- lateral = os.getenv("LATERAL", config[section].get("lateral", fallback="doji"))
21
- alta = os.getenv("ALTA", config[section].get("alta", fallback="verde"))
22
- baixa = os.getenv("BAIXA", config[section].get("baixa", fallback="vermelho"))
23
- rompimento_alta = os.getenv(
24
- "ROMPIMENTO_ALTA", config[section].get("rompimento_alta", fallback="c")
25
- )
26
- rompimento_baixa = os.getenv(
27
- "ROMPIMENTO_BAIXA", config[section].get("rompimento_baixa", fallback="v")
28
- )
29
- percentual_rompimento = int(
30
- os.getenv(
31
- "PERCENTUAL_ROMPIMENTO",
32
- config[section].getint("percentual_rompimento", fallback=50),
33
- )
34
- )
35
- percentual_doji = int(
36
- os.getenv("PERCENTUAL_DOJI", config[section].getint("percentual_doji", fallback=10))
37
- )
38
- up_bar = os.getenv("UP_BAR", config[section].get("up_bar", fallback="asc"))
39
- down_bar = os.getenv("DOWN_BAR", config[section].get("down_bar", fallback="desc"))
40
- inside_bar = os.getenv("INSIDE_BAR", config[section].get("inside_bar", fallback="ib"))
41
- outside_bar = os.getenv(
42
- "OUTSIDE_BAR", config[section].get("outside_bar", fallback="ob")
43
- )
44
- sombra_superior = os.getenv(
45
- "SOMBRA_SUPERIOR", config[section].get("sombra_superior", fallback="top")
46
- )
47
- sombra_inferior = os.getenv(
48
- "SOMBRA_INFERIOR", config[section].get("sombra_inferior", fallback="bottom")
49
- )
50
- data_source = dados = os.getenv("DADOS", config[section].get("dados", fallback="mt5"))
51
- csv_path = mt5_pasta = os.getenv(
52
- "MT5_PASTA", config[section].get("mt5_pasta", fallback="")
53
- )
54
-
55
-
56
- def get_data_source():
57
- from mtcli.data import CsvDataSource, MT5DataSource
58
-
59
- if data_source.lower() == "csv":
60
- return CsvDataSource()
61
- elif data_source.lower() == "mt5":
62
- return MT5DataSource()
63
- else:
64
- raise ValueError(f"Fonte de dados desconhecida: {data_source}")
65
-
66
-
67
- if not csv_path:
68
- conectar()
69
- terminal_info = mt5.terminal_info()
70
- if terminal_info is None:
71
- raise RuntimeError("Não foi possível obter as informações do terminal.")
72
-
73
- csv_path = terminal_info.data_path + "/MQL5/Files"
74
- shutdown()
75
-
76
- csv_path = csv_path.replace("\\", "/")
77
- csv_path += "/"
78
-
79
- timeframes = [
80
- "mn1",
81
- "w1",
82
- "d1",
83
- "h12",
84
- "h8",
85
- "h6",
86
- "h4",
87
- "h3",
88
- "h2",
89
- "h1",
90
- "m30",
91
- "m20",
92
- "m15",
93
- "m12",
94
- "m10",
95
- "m6",
96
- "m5",
97
- "m4",
98
- "m3",
99
- "m2",
100
- "m1",
101
- ]
1
+ import os
2
+ import MetaTrader5 as mt5
3
+ from mtcli.conecta import conectar, shutdown
4
+ from mtcli.models.conf_model import ConfModel
5
+
6
+
7
+ config = ConfModel("mtcli.ini").carregar()
8
+
9
+ section = "DEFAULT"
10
+ symbol = os.getenv("SYMBOL", config[section].get("symbol", fallback="WIN$N"))
11
+ digitos = int(os.getenv("DIGITOS", config[section].getint("digitos", fallback=2)))
12
+ PERIOD = period = os.getenv("PERIOD", config[section].get("period", fallback="D1"))
13
+ BARS = periodos = count = int(
14
+ os.getenv("COUNT", config[section].getint("count", fallback=999))
15
+ )
16
+ VIEW = view = os.getenv("VIEW", config[section].get("view", fallback="ch"))
17
+ VOLUME = volume = os.getenv("VOLUME", config[section].get("volume", fallback="tick"))
18
+ DATE = date = os.getenv("DATE", config[section].get("date", fallback=""))
19
+
20
+ lateral = os.getenv("LATERAL", config[section].get("lateral", fallback="doji"))
21
+ alta = os.getenv("ALTA", config[section].get("alta", fallback="verde"))
22
+ baixa = os.getenv("BAIXA", config[section].get("baixa", fallback="vermelho"))
23
+ rompimento_alta = os.getenv(
24
+ "ROMPIMENTO_ALTA", config[section].get("rompimento_alta", fallback="c")
25
+ )
26
+ rompimento_baixa = os.getenv(
27
+ "ROMPIMENTO_BAIXA", config[section].get("rompimento_baixa", fallback="v")
28
+ )
29
+ percentual_rompimento = int(
30
+ os.getenv(
31
+ "PERCENTUAL_ROMPIMENTO",
32
+ config[section].getint("percentual_rompimento", fallback=50),
33
+ )
34
+ )
35
+ percentual_doji = int(
36
+ os.getenv("PERCENTUAL_DOJI", config[section].getint("percentual_doji", fallback=10))
37
+ )
38
+ up_bar = os.getenv("UP_BAR", config[section].get("up_bar", fallback="asc"))
39
+ down_bar = os.getenv("DOWN_BAR", config[section].get("down_bar", fallback="desc"))
40
+ inside_bar = os.getenv("INSIDE_BAR", config[section].get("inside_bar", fallback="ib"))
41
+ outside_bar = os.getenv(
42
+ "OUTSIDE_BAR", config[section].get("outside_bar", fallback="ob")
43
+ )
44
+ sombra_superior = os.getenv(
45
+ "SOMBRA_SUPERIOR", config[section].get("sombra_superior", fallback="top")
46
+ )
47
+ sombra_inferior = os.getenv(
48
+ "SOMBRA_INFERIOR", config[section].get("sombra_inferior", fallback="bottom")
49
+ )
50
+ data_source = dados = os.getenv("DADOS", config[section].get("dados", fallback="mt5"))
51
+ csv_path = mt5_pasta = os.getenv(
52
+ "MT5_PASTA", config[section].get("mt5_pasta", fallback="")
53
+ )
54
+
55
+
56
+ def get_data_source():
57
+ from mtcli.data import CsvDataSource, MT5DataSource
58
+
59
+ if data_source.lower() == "csv":
60
+ return CsvDataSource()
61
+ elif data_source.lower() == "mt5":
62
+ return MT5DataSource()
63
+ else:
64
+ raise ValueError(f"Fonte de dados desconhecida: {data_source}")
65
+
66
+
67
+ if not csv_path:
68
+ conectar()
69
+ terminal_info = mt5.terminal_info()
70
+ if terminal_info is None:
71
+ raise RuntimeError("Não foi possível obter as informações do terminal.")
72
+
73
+ csv_path = terminal_info.data_path + "/MQL5/Files"
74
+ shutdown()
75
+
76
+ csv_path = csv_path.replace("\\", "/")
77
+ csv_path += "/"
78
+
79
+ TIMEFRAMES = timeframes = [
80
+ "mn1",
81
+ "w1",
82
+ "d1",
83
+ "h12",
84
+ "h8",
85
+ "h6",
86
+ "h4",
87
+ "h3",
88
+ "h2",
89
+ "h1",
90
+ "m30",
91
+ "m20",
92
+ "m15",
93
+ "m12",
94
+ "m10",
95
+ "m6",
96
+ "m5",
97
+ "m4",
98
+ "m3",
99
+ "m2",
100
+ "m1",
101
+ ]
@@ -1,97 +1,97 @@
1
- """Módulo fonte de dados via API do MetaTrader 5."""
2
-
3
- from datetime import datetime
4
-
5
- import MetaTrader5 as mt5
6
-
7
- from mtcli.logger import setup_logger
8
- from mtcli.mt5_context import mt5_conexao
9
-
10
- from .base import DataSourceBase
11
-
12
- log = setup_logger()
13
-
14
-
15
- class MT5DataSource(DataSourceBase):
16
- """Fonte de dados via API do MetaTrader 5."""
17
-
18
- def get_data(self, symbol, period, count=100):
19
- """Retorna uma lista de lista de cotações do MetaTrader."""
20
- period = period.upper()
21
- log.info(
22
- f"Iniciando coleta de dados via API MT5: {symbol} no timeframe {period}"
23
- )
24
- tf_map = {
25
- "M1": mt5.TIMEFRAME_M1,
26
- "M2": mt5.TIMEFRAME_M2,
27
- "M3": mt5.TIMEFRAME_M3,
28
- "M4": mt5.TIMEFRAME_M4,
29
- "M5": mt5.TIMEFRAME_M5,
30
- "M6": mt5.TIMEFRAME_M6,
31
- "M10": mt5.TIMEFRAME_M10,
32
- "M12": mt5.TIMEFRAME_M12,
33
- "M15": mt5.TIMEFRAME_M15,
34
- "M20": mt5.TIMEFRAME_M20,
35
- "M30": mt5.TIMEFRAME_M30,
36
- "H1": mt5.TIMEFRAME_H1,
37
- "H2": mt5.TIMEFRAME_H2,
38
- "H3": mt5.TIMEFRAME_H3,
39
- "H4": mt5.TIMEFRAME_H4,
40
- "H6": mt5.TIMEFRAME_H6,
41
- "H8": mt5.TIMEFRAME_H8,
42
- "H12": mt5.TIMEFRAME_H12,
43
- "D1": mt5.TIMEFRAME_D1,
44
- "W1": mt5.TIMEFRAME_W1,
45
- "MN1": mt5.TIMEFRAME_MN1,
46
- }
47
-
48
- if period.upper() not in tf_map:
49
- log.error(f"Timeframe inválido: {period}.")
50
- raise ValueError(f"Timeframe '{period}' inválido.")
51
-
52
- corretoras_b3 = [
53
- "clear",
54
- "xp",
55
- "rico",
56
- "modal",
57
- "terra",
58
- "btg",
59
- "toro",
60
- ]
61
-
62
- with mt5_conexao():
63
- for corretora in corretoras_b3:
64
- symbol = (
65
- symbol.upper()
66
- if corretora in mt5.account_info().company.lower()
67
- else symbol
68
- )
69
- log.info(
70
- f"Finalizada verificacao da corretora para tratar symbol: {symbol}."
71
- )
72
-
73
- rates = mt5.copy_rates_from_pos(symbol, tf_map[period], 0, count)
74
-
75
- if rates is None:
76
- log.warning("Nenum dado retornado da API MT5.")
77
- raise ValueError("Nenhum dado retornado da API MT5.")
78
-
79
- result = []
80
- for r in rates:
81
- dt_str = (
82
- r["time"].astype("datetime64[s]").item().strftime("%Y.%m.%d %H:%M:%S")
83
- )
84
- result.append(
85
- [
86
- dt_str,
87
- r["open"],
88
- r["high"],
89
- r["low"],
90
- r["close"],
91
- r["tick_volume"],
92
- r["real_volume"],
93
- ]
94
- )
95
-
96
- log.info("Coleta de dados via API MT5 finalizada.")
97
- return result
1
+ """Módulo fonte de dados via API do MetaTrader 5."""
2
+
3
+ from datetime import datetime
4
+
5
+ import MetaTrader5 as mt5
6
+
7
+ from mtcli.logger import setup_logger
8
+ from mtcli.mt5_context import mt5_conexao
9
+
10
+ from .base import DataSourceBase
11
+
12
+ log = setup_logger()
13
+
14
+
15
+ class MT5DataSource(DataSourceBase):
16
+ """Fonte de dados via API do MetaTrader 5."""
17
+
18
+ def get_data(self, symbol, period, count=100):
19
+ """Retorna uma lista de lista de cotações do MetaTrader."""
20
+ period = period.upper()
21
+ log.info(
22
+ f"Iniciando coleta de dados via API MT5: {symbol} no timeframe {period}"
23
+ )
24
+ tf_map = {
25
+ "M1": mt5.TIMEFRAME_M1,
26
+ "M2": mt5.TIMEFRAME_M2,
27
+ "M3": mt5.TIMEFRAME_M3,
28
+ "M4": mt5.TIMEFRAME_M4,
29
+ "M5": mt5.TIMEFRAME_M5,
30
+ "M6": mt5.TIMEFRAME_M6,
31
+ "M10": mt5.TIMEFRAME_M10,
32
+ "M12": mt5.TIMEFRAME_M12,
33
+ "M15": mt5.TIMEFRAME_M15,
34
+ "M20": mt5.TIMEFRAME_M20,
35
+ "M30": mt5.TIMEFRAME_M30,
36
+ "H1": mt5.TIMEFRAME_H1,
37
+ "H2": mt5.TIMEFRAME_H2,
38
+ "H3": mt5.TIMEFRAME_H3,
39
+ "H4": mt5.TIMEFRAME_H4,
40
+ "H6": mt5.TIMEFRAME_H6,
41
+ "H8": mt5.TIMEFRAME_H8,
42
+ "H12": mt5.TIMEFRAME_H12,
43
+ "D1": mt5.TIMEFRAME_D1,
44
+ "W1": mt5.TIMEFRAME_W1,
45
+ "MN1": mt5.TIMEFRAME_MN1,
46
+ }
47
+
48
+ if period.upper() not in tf_map:
49
+ log.error(f"Timeframe inválido: {period}.")
50
+ raise ValueError(f"Timeframe '{period}' inválido.")
51
+
52
+ corretoras_b3 = [
53
+ "clear",
54
+ "xp",
55
+ "rico",
56
+ "modal",
57
+ "terra",
58
+ "btg",
59
+ "toro",
60
+ ]
61
+
62
+ with mt5_conexao():
63
+ for corretora in corretoras_b3:
64
+ symbol = (
65
+ symbol.upper()
66
+ if corretora in mt5.account_info().company.lower()
67
+ else symbol
68
+ )
69
+ log.info(
70
+ f"Finalizada verificacao da corretora para tratar symbol: {symbol}."
71
+ )
72
+
73
+ rates = mt5.copy_rates_from_pos(symbol, tf_map[period], 0, count)
74
+
75
+ if rates is None:
76
+ log.warning("Nenum dado retornado da API MT5.")
77
+ raise ValueError("Nenhum dado retornado da API MT5.")
78
+
79
+ result = []
80
+ for r in rates:
81
+ dt_str = (
82
+ r["time"].astype("datetime64[s]").item().strftime("%Y.%m.%d %H:%M:%S")
83
+ )
84
+ result.append(
85
+ [
86
+ dt_str,
87
+ r["open"],
88
+ r["high"],
89
+ r["low"],
90
+ r["close"],
91
+ r["tick_volume"],
92
+ r["real_volume"],
93
+ ]
94
+ )
95
+
96
+ log.info("Coleta de dados via API MT5 finalizada.")
97
+ return result
@@ -1,45 +1,45 @@
1
- import logging
2
- from logging.handlers import RotatingFileHandler
3
- import os
4
-
5
- LOG_DIR = os.path.join(os.path.expanduser("~"), ".mtcli")
6
- os.makedirs(LOG_DIR, exist_ok=True)
7
- LOG_FILE = os.path.join(LOG_DIR, "mtcli.log")
8
-
9
-
10
- def setup_logger(name: str = "mtcli") -> logging.Logger:
11
- """Configura logger rotativo com saída em arquivo e console.
12
-
13
- - Escreve logs em ~/.mtcli/mtcli.log (máx. 2 MB, 3 backups).
14
- - Mostra logs também no console (stdout), capturáveis via pytest/caplog.
15
- - Evita duplicar handlers.
16
- """
17
-
18
- logger = logging.getLogger(name)
19
- logger.setLevel(logging.DEBUG)
20
-
21
- formatter = logging.Formatter(
22
- "%(asctime)s | %(levelname)-8s | %(name)s | %(message)s",
23
- datefmt="%Y-%m-%d %H:%M:%S",
24
- )
25
-
26
- # === File handler rotativo ===
27
- if not any(isinstance(h, RotatingFileHandler) for h in logger.handlers):
28
- file_handler = RotatingFileHandler(LOG_FILE, maxBytes=2_000_000, backupCount=3)
29
- file_handler.setFormatter(formatter)
30
- logger.addHandler(file_handler)
31
-
32
- # === Stream handler (console) ===
33
- if not any(isinstance(h, logging.StreamHandler) for h in logger.handlers):
34
- console_handler = logging.StreamHandler()
35
- console_handler.setFormatter(formatter)
36
- logger.addHandler(console_handler)
37
-
38
- # Permite que pytest caplog capture logs
39
- logger.propagate = True
40
-
41
- return logger
42
-
43
-
44
- # Inicializa logger padrão
45
- log = setup_logger()
1
+ import logging
2
+ from logging.handlers import RotatingFileHandler
3
+ import os
4
+
5
+ LOG_DIR = os.path.join(os.path.expanduser("~"), ".mtcli")
6
+ os.makedirs(LOG_DIR, exist_ok=True)
7
+ LOG_FILE = os.path.join(LOG_DIR, "mtcli.log")
8
+
9
+
10
+ def setup_logger(name: str = "mtcli") -> logging.Logger:
11
+ """Configura logger rotativo com saída em arquivo e console.
12
+
13
+ - Escreve logs em ~/.mtcli/mtcli.log (máx. 2 MB, 3 backups).
14
+ - Mostra logs também no console (stdout), capturáveis via pytest/caplog.
15
+ - Evita duplicar handlers.
16
+ """
17
+
18
+ logger = logging.getLogger(name)
19
+ logger.setLevel(logging.DEBUG)
20
+
21
+ formatter = logging.Formatter(
22
+ "%(asctime)s | %(levelname)-8s | %(name)s | %(message)s",
23
+ datefmt="%Y-%m-%d %H:%M:%S",
24
+ )
25
+
26
+ # === File handler rotativo ===
27
+ if not any(isinstance(h, RotatingFileHandler) for h in logger.handlers):
28
+ file_handler = RotatingFileHandler(LOG_FILE, maxBytes=2_000_000, backupCount=3)
29
+ file_handler.setFormatter(formatter)
30
+ logger.addHandler(file_handler)
31
+
32
+ # === Stream handler (console) ===
33
+ if not any(isinstance(h, logging.StreamHandler) for h in logger.handlers):
34
+ console_handler = logging.StreamHandler()
35
+ console_handler.setFormatter(formatter)
36
+ logger.addHandler(console_handler)
37
+
38
+ # Permite que pytest caplog capture logs
39
+ logger.propagate = True
40
+
41
+ return logger
42
+
43
+
44
+ # Inicializa logger padrão
45
+ log = setup_logger()
@@ -1,33 +1,33 @@
1
- """
2
- Gerencia o ciclo de conexão com o MetaTrader 5.
3
- Fornece o contexto 'mt5_conexao' para uso seguro em blocos with.
4
- """
5
-
6
- from contextlib import contextmanager
7
- from mtcli.logger import setup_logger
8
- from mtcli.conecta import conectar, shutdown
9
-
10
- log = setup_logger()
11
-
12
-
13
- @contextmanager
14
- def mt5_conexao():
15
- """
16
- Context manager para conexão com o MetaTrader 5.
17
- - Chama `conectar()` ao entrar no contexto.
18
- - Chama `shutdown()` ao sair.
19
- - Loga falhas e garante fechamento seguro.
20
- """
21
- try:
22
- log.debug("Inicializando conexao com MetaTrader 5...")
23
- conectar()
24
- yield
25
- except Exception as e:
26
- log.error(f"Erro ao conectar ao MetaTrader 5: {e}")
27
- raise
28
- finally:
29
- try:
30
- shutdown()
31
- log.debug("Conexao com MetaTrader 5 encerrada.")
32
- except Exception as e:
33
- log.error(f"Erro ao encerrar conexao MT5: {e}")
1
+ """
2
+ Gerencia o ciclo de conexão com o MetaTrader 5.
3
+ Fornece o contexto 'mt5_conexao' para uso seguro em blocos with.
4
+ """
5
+
6
+ from contextlib import contextmanager
7
+ from mtcli.logger import setup_logger
8
+ from mtcli.conecta import conectar, shutdown
9
+
10
+ log = setup_logger()
11
+
12
+
13
+ @contextmanager
14
+ def mt5_conexao():
15
+ """
16
+ Context manager para conexão com o MetaTrader 5.
17
+ - Chama `conectar()` ao entrar no contexto.
18
+ - Chama `shutdown()` ao sair.
19
+ - Loga falhas e garante fechamento seguro.
20
+ """
21
+ try:
22
+ log.debug("Inicializando conexao com MetaTrader 5...")
23
+ conectar()
24
+ yield
25
+ except Exception as e:
26
+ log.error(f"Erro ao conectar ao MetaTrader 5: {e}")
27
+ raise
28
+ finally:
29
+ try:
30
+ shutdown()
31
+ log.debug("Conexao com MetaTrader 5 encerrada.")
32
+ except Exception as e:
33
+ log.error(f"Erro ao encerrar conexao MT5: {e}")
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "mtcli"
3
- version = "3.2.0-dev2"
3
+ version = "3.2.1"
4
4
  description = "Aplicativo CLI para exibir gráficos do MetaTrader 5 em texto acessível ao leitor de telas"
5
5
  authors = [
6
6
  {name = "Valmir França da Silva",email = "vfranca3@gmail.com"}
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