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.
- mtcli/cli.py +2 -50
- mtcli/commands/bars.py +66 -138
- mtcli/conf.py +125 -331
- mtcli/controllers/bars_controller.py +75 -0
- mtcli/data/base.py +20 -9
- mtcli/data/csv.py +46 -14
- mtcli/data/factory.py +29 -0
- mtcli/data/mt5.py +123 -70
- mtcli/domain/bar.py +40 -0
- mtcli/domain/calculations.py +6 -0
- mtcli/domain/config.py +4 -0
- mtcli/domain/pattern.py +10 -0
- mtcli/domain/price.py +13 -0
- mtcli/domain/result.py +8 -0
- mtcli/domain/session.py +11 -0
- mtcli/domain/structure.py +7 -0
- mtcli/domain/symbol.py +10 -0
- mtcli/domain/tick.py +9 -0
- mtcli/domain/timeframe.py +15 -0
- mtcli/logger.py +57 -99
- mtcli/models/bars_model.py +175 -21
- mtcli/models/rate_model.py +71 -0
- mtcli/models_legado/__init__.py +1 -0
- mtcli/{models → models_legado}/bar_model.py +105 -105
- mtcli/models_legado/bars_model.py +25 -0
- mtcli/models_legado/chart.py +26 -0
- mtcli/models_legado/consecutive.py +29 -0
- mtcli/mt5_context.py +5 -1
- mtcli/plugin.py +18 -18
- mtcli/plugins/media_movel/cli.py +38 -63
- mtcli/plugins/media_movel/conf.py +74 -3
- mtcli/plugins/media_movel/controller.py +43 -0
- mtcli/plugins/media_movel/tests/test_mm.py +1 -1
- mtcli/plugins/media_movel/tests/test_model_media_movel.py +1 -1
- mtcli/plugins/media_movel/view.py +15 -0
- mtcli/plugins/range_medio/cli.py +2 -2
- mtcli/plugins/range_medio/conf.py +67 -1
- mtcli/plugins/range_medio/models/average_range_model.py +3 -3
- mtcli/plugins/volume_medio/cli.py +2 -2
- mtcli/plugins/volume_medio/conf.py +67 -1
- mtcli/plugins/volume_medio/models/model_average_volume.py +3 -3
- mtcli/utils/time.py +65 -65
- mtcli/views/base_view.py +80 -0
- mtcli/views/factory_view.py +30 -0
- mtcli/views/full_view.py +37 -62
- mtcli/views/hl_view.py +32 -0
- mtcli/views/range_view.py +47 -0
- mtcli/views/rate_view.py +18 -0
- mtcli/views/volume_view.py +62 -0
- {mtcli-3.8.0.dev17.dist-info → mtcli-4.0.0.dev1.dist-info}/METADATA +1 -1
- mtcli-4.0.0.dev1.dist-info/RECORD +84 -0
- mtcli/cli_dev.py +0 -8
- mtcli/commands/backfill.py +0 -70
- mtcli/commands/ticks.py +0 -58
- mtcli/commands_dev/migrate.py +0 -48
- mtcli/database.py +0 -137
- mtcli/marketdata/__init__.py +0 -0
- mtcli/marketdata/backfill_engine.py +0 -136
- mtcli/marketdata/tick_bus.py +0 -41
- mtcli/marketdata/tick_cache.py +0 -160
- mtcli/marketdata/tick_engine.py +0 -87
- mtcli/marketdata/tick_repository.py +0 -333
- mtcli/marketdata/tick_writer.py +0 -44
- mtcli/marketdata/trade_tick_filter.py +0 -39
- mtcli/migrations/001_initial_schema.py +0 -51
- mtcli/migrations/002_ticks_time_msc.py +0 -53
- mtcli/migrations/003_optimize_ticks_without_rowid.py +0 -86
- mtcli/migrations/004_ticks_pk_time_msc.py +0 -78
- mtcli/migrations/005_tick_price_compression.py +0 -86
- mtcli/migrations/006_add_index_ticks_symbol_time.py +0 -32
- mtcli/migrations/007_deduplicate_ticks_and_add_unique_index.py +0 -91
- mtcli/migrations/008_fix_ticks_unique_index.py +0 -98
- mtcli/migrations/009_keep_only_trade_ticks.py +0 -84
- mtcli/migrations/__init__.py +0 -0
- mtcli/migrations/__main__.py +0 -7
- mtcli/migrations/runner.py +0 -301
- mtcli/models/chart_model.py +0 -155
- mtcli/models/conf_model.py +0 -32
- mtcli/models/consecutive_bars_model.py +0 -77
- mtcli/models/signals_model.py +0 -100
- mtcli/models/unconsecutive_bar_model.py +0 -67
- mtcli/plugins/media_movel/models/__init__.py +0 -1
- mtcli/services/__init__.py +0 -0
- mtcli/services/maintenance_service.py +0 -170
- mtcli/services/tick_service.py +0 -56
- mtcli/views/close_view.py +0 -37
- mtcli/views/high_view.py +0 -37
- mtcli/views/low_view.py +0 -37
- mtcli/views/min_view.py +0 -42
- mtcli/views/open_view.py +0 -37
- mtcli/views/ranges_view.py +0 -41
- mtcli/views/rates_view.py +0 -41
- mtcli/views/vars_view.py +0 -46
- mtcli/views/volumes_view.py +0 -51
- mtcli-3.8.0.dev17.dist-info/RECORD +0 -102
- /mtcli/{commands_dev → controllers}/__init__.py +0 -0
- /mtcli/{models → models_legado}/rates_model.py +0 -0
- /mtcli/plugins/media_movel/{models/model_media_movel.py → model.py} +0 -0
- {mtcli-3.8.0.dev17.dist-info → mtcli-4.0.0.dev1.dist-info}/WHEEL +0 -0
- {mtcli-3.8.0.dev17.dist-info → mtcli-4.0.0.dev1.dist-info}/entry_points.txt +0 -0
- {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
|
|
8
|
-
from
|
|
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
|
-
"""
|
|
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
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
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
|
-
|
|
22
|
+
VOLUME_TYPE,
|
|
12
23
|
)
|
|
13
|
-
from
|
|
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
|
-
|
|
29
|
-
|
|
30
|
-
)
|
|
31
|
-
@click.
|
|
32
|
-
@click.option(
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
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
|
-
|
|
147
|
-
|
|
74
|
+
for line in lines:
|
|
75
|
+
click.echo(line)
|