mtcli 3.8.0.dev17__py3-none-any.whl → 4.0.0.dev1__py3-none-any.whl

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 (101) hide show
  1. mtcli/cli.py +2 -50
  2. mtcli/commands/bars.py +66 -138
  3. mtcli/conf.py +125 -331
  4. mtcli/controllers/bars_controller.py +75 -0
  5. mtcli/data/base.py +20 -9
  6. mtcli/data/csv.py +46 -14
  7. mtcli/data/factory.py +29 -0
  8. mtcli/data/mt5.py +123 -70
  9. mtcli/domain/bar.py +40 -0
  10. mtcli/domain/calculations.py +6 -0
  11. mtcli/domain/config.py +4 -0
  12. mtcli/domain/pattern.py +10 -0
  13. mtcli/domain/price.py +13 -0
  14. mtcli/domain/result.py +8 -0
  15. mtcli/domain/session.py +11 -0
  16. mtcli/domain/structure.py +7 -0
  17. mtcli/domain/symbol.py +10 -0
  18. mtcli/domain/tick.py +9 -0
  19. mtcli/domain/timeframe.py +15 -0
  20. mtcli/logger.py +57 -99
  21. mtcli/models/bars_model.py +175 -21
  22. mtcli/models/rate_model.py +71 -0
  23. mtcli/models_legado/__init__.py +1 -0
  24. mtcli/{models → models_legado}/bar_model.py +105 -105
  25. mtcli/models_legado/bars_model.py +25 -0
  26. mtcli/models_legado/chart.py +26 -0
  27. mtcli/models_legado/consecutive.py +29 -0
  28. mtcli/mt5_context.py +5 -1
  29. mtcli/plugin.py +18 -18
  30. mtcli/plugins/media_movel/cli.py +38 -63
  31. mtcli/plugins/media_movel/conf.py +74 -3
  32. mtcli/plugins/media_movel/controller.py +43 -0
  33. mtcli/plugins/media_movel/tests/test_mm.py +1 -1
  34. mtcli/plugins/media_movel/tests/test_model_media_movel.py +1 -1
  35. mtcli/plugins/media_movel/view.py +15 -0
  36. mtcli/plugins/range_medio/cli.py +2 -2
  37. mtcli/plugins/range_medio/conf.py +67 -1
  38. mtcli/plugins/range_medio/models/average_range_model.py +3 -3
  39. mtcli/plugins/volume_medio/cli.py +2 -2
  40. mtcli/plugins/volume_medio/conf.py +67 -1
  41. mtcli/plugins/volume_medio/models/model_average_volume.py +3 -3
  42. mtcli/utils/time.py +65 -65
  43. mtcli/views/base_view.py +80 -0
  44. mtcli/views/factory_view.py +30 -0
  45. mtcli/views/full_view.py +37 -62
  46. mtcli/views/hl_view.py +32 -0
  47. mtcli/views/range_view.py +47 -0
  48. mtcli/views/rate_view.py +18 -0
  49. mtcli/views/volume_view.py +62 -0
  50. {mtcli-3.8.0.dev17.dist-info → mtcli-4.0.0.dev1.dist-info}/METADATA +1 -1
  51. mtcli-4.0.0.dev1.dist-info/RECORD +84 -0
  52. mtcli/cli_dev.py +0 -8
  53. mtcli/commands/backfill.py +0 -70
  54. mtcli/commands/ticks.py +0 -58
  55. mtcli/commands_dev/migrate.py +0 -48
  56. mtcli/database.py +0 -137
  57. mtcli/marketdata/__init__.py +0 -0
  58. mtcli/marketdata/backfill_engine.py +0 -136
  59. mtcli/marketdata/tick_bus.py +0 -41
  60. mtcli/marketdata/tick_cache.py +0 -160
  61. mtcli/marketdata/tick_engine.py +0 -87
  62. mtcli/marketdata/tick_repository.py +0 -333
  63. mtcli/marketdata/tick_writer.py +0 -44
  64. mtcli/marketdata/trade_tick_filter.py +0 -39
  65. mtcli/migrations/001_initial_schema.py +0 -51
  66. mtcli/migrations/002_ticks_time_msc.py +0 -53
  67. mtcli/migrations/003_optimize_ticks_without_rowid.py +0 -86
  68. mtcli/migrations/004_ticks_pk_time_msc.py +0 -78
  69. mtcli/migrations/005_tick_price_compression.py +0 -86
  70. mtcli/migrations/006_add_index_ticks_symbol_time.py +0 -32
  71. mtcli/migrations/007_deduplicate_ticks_and_add_unique_index.py +0 -91
  72. mtcli/migrations/008_fix_ticks_unique_index.py +0 -98
  73. mtcli/migrations/009_keep_only_trade_ticks.py +0 -84
  74. mtcli/migrations/__init__.py +0 -0
  75. mtcli/migrations/__main__.py +0 -7
  76. mtcli/migrations/runner.py +0 -301
  77. mtcli/models/chart_model.py +0 -155
  78. mtcli/models/conf_model.py +0 -32
  79. mtcli/models/consecutive_bars_model.py +0 -77
  80. mtcli/models/signals_model.py +0 -100
  81. mtcli/models/unconsecutive_bar_model.py +0 -67
  82. mtcli/plugins/media_movel/models/__init__.py +0 -1
  83. mtcli/services/__init__.py +0 -0
  84. mtcli/services/maintenance_service.py +0 -170
  85. mtcli/services/tick_service.py +0 -56
  86. mtcli/views/close_view.py +0 -37
  87. mtcli/views/high_view.py +0 -37
  88. mtcli/views/low_view.py +0 -37
  89. mtcli/views/min_view.py +0 -42
  90. mtcli/views/open_view.py +0 -37
  91. mtcli/views/ranges_view.py +0 -41
  92. mtcli/views/rates_view.py +0 -41
  93. mtcli/views/vars_view.py +0 -46
  94. mtcli/views/volumes_view.py +0 -51
  95. mtcli-3.8.0.dev17.dist-info/RECORD +0 -102
  96. /mtcli/{commands_dev → controllers}/__init__.py +0 -0
  97. /mtcli/{models → models_legado}/rates_model.py +0 -0
  98. /mtcli/plugins/media_movel/{models/model_media_movel.py → model.py} +0 -0
  99. {mtcli-3.8.0.dev17.dist-info → mtcli-4.0.0.dev1.dist-info}/WHEEL +0 -0
  100. {mtcli-3.8.0.dev17.dist-info → mtcli-4.0.0.dev1.dist-info}/entry_points.txt +0 -0
  101. {mtcli-3.8.0.dev17.dist-info → mtcli-4.0.0.dev1.dist-info}/licenses/LICENSE +0 -0
mtcli/cli.py CHANGED
@@ -4,57 +4,14 @@ CLI principal do mtcli.
4
4
 
5
5
  import os
6
6
  import click
7
- from mtcli.plugin_loader import load_plugins
8
- from mtcli.logger import setup_logger
9
- from mtcli.services.tick_service import ensure_tick_engine
7
+ from .plugin_loader import load_plugins
8
+ from .logger import setup_logger
10
9
 
11
10
  from .commands.bars import bars
12
11
  from .commands.doctor import doctor
13
- from .commands.ticks import ticks
14
- from .commands.backfill import backfill
15
12
 
16
13
  logger = setup_logger(__name__)
17
14
 
18
- _tick_engines = []
19
-
20
-
21
- def start_tick_capture():
22
- """
23
- Inicia captura contínua de ticks em background se MTCLI_SYMBOL estiver definido.
24
- """
25
-
26
- global _tick_engines
27
-
28
- if _tick_engines:
29
- return
30
-
31
- symbols = os.getenv("MTCLI_SYMBOL")
32
-
33
- if not symbols:
34
- logger.info(
35
- "Captura automática de ticks desativada (MTCLI_SYMBOL não definido)."
36
- )
37
- return
38
-
39
- if isinstance(symbols, str):
40
- symbols = [symbols]
41
-
42
- logger.info("Iniciando captura contínua de ticks para %s", symbols)
43
-
44
- try:
45
- for symbol in symbols:
46
- engine = ensure_tick_engine(symbol)
47
- _tick_engines.append(engine)
48
- # pode rodar em thread se quiser background
49
- import threading
50
- t = threading.Thread(target=engine.start, daemon=True)
51
- t.start()
52
-
53
- logger.info("Captura de ticks iniciada em background.")
54
-
55
- except Exception:
56
- logger.exception("Falha ao iniciar captura de ticks")
57
-
58
15
 
59
16
  @click.group(context_settings={"max_content_width": 120}, invoke_without_command=True)
60
17
  @click.version_option(package_name="mtcli")
@@ -64,17 +21,12 @@ def mt(ctx):
64
21
  CLI principal do mtcli.
65
22
  """
66
23
 
67
- start_tick_capture()
68
-
69
24
  if ctx.invoked_subcommand is None:
70
25
  click.echo(ctx.get_help())
71
26
 
72
27
 
73
28
  mt.add_command(doctor, name="doctor")
74
29
  mt.add_command(bars, name="bars")
75
- mt.add_command(doctor, name="dr")
76
- mt.add_command(ticks)
77
- mt.add_command(backfill, name="fill")
78
30
 
79
31
  loaded_plugins = load_plugins(mt)
80
32
  logger.info("Plugins carregados: %s", loaded_plugins)
mtcli/commands/bars.py CHANGED
@@ -1,147 +1,75 @@
1
- """Exibe o gráfico de barras."""
1
+ """
2
+ Comando CLI `bars`.
3
+
4
+ Responsável por:
5
+ - receber parâmetros via terminal (Click)
6
+ - instanciar a fonte de dados
7
+ - delegar execução ao BarsController
8
+ - imprimir saída no terminal
9
+
10
+ Este comando é a camada de entrada (CLI) no padrão MVC do mtcli.
11
+ """
2
12
 
3
13
  import click
4
14
 
5
- from mtcli.conf import (
6
- BARS,
7
- DATE,
8
- PERIOD,
9
- TIMEFRAMES,
15
+ from ..controllers.bars_controller import BarsController
16
+ from ..conf import (
17
+ DATA_SOURCE_NAME,
18
+ SYMBOL,
19
+ TIMEFRAME,
20
+ MAX_BARS,
10
21
  VIEW,
11
- VOLUME,
22
+ VOLUME_TYPE,
12
23
  )
13
- from mtcli.models.bars_model import BarsModel
14
- from mtcli.models.rates_model import RatesModel
15
- from mtcli.views.close_view import CloseView
16
- from mtcli.views.full_view import FullView
17
- from mtcli.views.high_view import HighView
18
- from mtcli.views.low_view import LowView
19
- from mtcli.views.min_view import MinView
20
- from mtcli.views.open_view import OpenView
21
- from mtcli.views.ranges_view import RangesView
22
- from mtcli.views.rates_view import RatesView
23
- from mtcli.views.vars_view import VarsView
24
- from mtcli.views.volumes_view import VolumesView
24
+ from ..data.factory import create_data_source
25
25
 
26
26
 
27
- @click.command(
28
- "bars",
29
- help="Mostra o gráfico de candles em texto para o ativo e período especificados.",
30
- )
31
- @click.argument("symbol")
32
- @click.option(
33
- "--view",
34
- "-v",
35
- type=click.Choice(
36
- [
37
- "ch",
38
- "m",
39
- "hl",
40
- "f",
41
- "full",
42
- "r",
43
- "range",
44
- "v",
45
- "volume",
46
- "va",
47
- "percentual",
48
- "oh",
49
- "ohlc",
50
- "o",
51
- "open",
52
- "h",
53
- "high",
54
- "l",
55
- "low",
56
- "c",
57
- "close",
58
- ],
59
- case_sensitive=False,
60
- ),
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.",
64
- )
65
- @click.option(
66
- "--period",
67
- "-p",
68
- type=click.Choice(TIMEFRAMES, case_sensitive=False),
69
- default=PERIOD,
70
- show_default=True,
71
- help="Timeframe das barras.",
72
- )
73
- @click.option(
74
- "--count",
75
- "-c",
76
- type=int,
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.",
95
- )
96
- @click.option(
97
- "--show-date",
98
- "-sd",
99
- is_flag=True,
100
- default=False,
101
- show_default=True,
102
- help="Ativa a datacao das barras.",
103
- )
104
- @click.option(
105
- "--volume",
106
- "-vo",
107
- type=click.Choice(["tick", "real"], case_sensitive=False),
108
- default=VOLUME,
109
- show_default=True,
110
- help="Tipo de volume.",
111
- )
112
- def bars(symbol, view, period, count, date, numerator, show_date, volume):
113
- """Exibe o grafico do MetaTrader 5."""
114
- period = period.lower()
115
- view = view.lower()
116
- rates = RatesModel(symbol, period, count).get_data()
117
- bars = BarsModel(rates, date).get_bars()
118
- views = []
119
- if view in ["m", "ch", "hl"]: # máximas e mínimas
120
- views = MinView(bars, count, period, date, numerator, show_date).views()
121
- elif view in ["r", "range"]: # ranges
122
- views = RangesView(bars, count, period, date, numerator, show_date).views()
123
- elif view in ["oh", "ohlc"]: # OHLC
124
- views = RatesView(bars, count, period, date, numerator, show_date).views()
125
- elif view in ["va", "percentual"]: # variações percentuais
126
- views = VarsView(bars, count, period, date, numerator, show_date).views()
127
- elif view in ["o", "open"]: # abertura
128
- views = OpenView(bars, count, period, date, numerator, show_date).views()
129
- elif view in ["h", "high"]: # máximas
130
- views = HighView(bars, count, period, date, numerator, show_date).views()
131
- elif view in ["l", "low"]: # mínimas
132
- views = LowView(bars, count, period, date, numerator, show_date).views()
133
- elif view in ["c", "close"]: # fechamentos
134
- views = CloseView(bars, count, period, date, numerator, show_date).views()
135
- elif view in ["v", "volume"]: # volumes
136
- views = VolumesView(
137
- bars, count, period, date, numerator, show_date, volume
138
- ).views()
139
- else: # completo
140
- views = FullView(bars, count, period, date, numerator, show_date).views()
141
- if views:
142
- for view in views:
143
- click.echo(view)
27
+ @click.command()
28
+ @click.option("--symbol", "-s", default=SYMBOL, show_default=True, help="Código do ativo (ex: WINM26)")
29
+ @click.option("--timeframe", "-t", "period", default=TIMEFRAME, show_default=True, help="Timeframe (ex: M1, M5, D1)")
30
+ @click.option("--max-bars", "-mb", "count", default=MAX_BARS, show_default=True, help="Quantidade de barras")
31
+ @click.option("--view", "-v", default=VIEW, show_default=True, help="Formato da view (hl_view, full_view, etc)")
32
+ @click.option("--date", "-d", default=None, show_default=True, help="Filtrar pregão (YYYY-MM-DD)")
33
+ @click.option("--numerator", "-n", is_flag=True, show_default=True, help="Numerar barras")
34
+ @click.option("--show-date", "-sd", is_flag=True, show_default=True, help="Exibir data/hora")
35
+ @click.option("--volume-type", "-vt", "volume", default=VOLUME_TYPE, show_default=True, help="Tipo de volume (tick/real)")
36
+ @click.option("--data-source", "-ds", "source", default=None, show_default=True, help="Fonte de dados (mt5/csv)")
37
+ def bars(symbol, period, count, view, date, numerator, show_date, volume, source):
38
+ """
39
+ Executa o comando `bars`.
40
+
41
+ Fluxo:
42
+ 1. Resolve fonte de dados
43
+ 2. Executa controller
44
+ 3. Renderiza saída linha a linha
45
+
46
+ Args:
47
+ symbol (str): Ativo
48
+ period (str): Timeframe
49
+ count (int): Quantidade de barras
50
+ view (str): Nome da view
51
+ date (str | None): Filtro de pregão
52
+ numerator (bool): Numerar barras
53
+ show_date (bool): Mostrar timestamp
54
+ volume (str | None): Tipo de volume
55
+ source (str | None): Fonte de dados
56
+ """
57
+
58
+ source_name = source or DATA_SOURCE_NAME
59
+ data_source = create_data_source(source_name)
60
+
61
+ controller = BarsController(data_source)
144
62
 
63
+ lines = controller.execute(
64
+ symbol=symbol,
65
+ period=period,
66
+ count=count,
67
+ date=date,
68
+ view=view,
69
+ numerator=numerator,
70
+ show_date=show_date,
71
+ volume=volume,
72
+ )
145
73
 
146
- if __name__ == "__main__":
147
- bars()
74
+ for line in lines:
75
+ click.echo(line)