mtcli 3.2.1__tar.gz → 3.3.0.dev0__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-3.2.1 → mtcli-3.3.0.dev0}/PKG-INFO +1 -1
- {mtcli-3.2.1 → mtcli-3.3.0.dev0}/mtcli/commands/bars.py +147 -147
- {mtcli-3.2.1 → mtcli-3.3.0.dev0}/mtcli/commands/conf.py +1 -1
- {mtcli-3.2.1 → mtcli-3.3.0.dev0}/mtcli/commands/logs.py +42 -40
- {mtcli-3.2.1 → mtcli-3.3.0.dev0}/mtcli/conecta.py +1 -0
- {mtcli-3.2.1 → mtcli-3.3.0.dev0}/mtcli/conf.py +102 -101
- {mtcli-3.2.1 → mtcli-3.3.0.dev0}/mtcli/data/mt5.py +0 -2
- {mtcli-3.2.1 → mtcli-3.3.0.dev0}/mtcli/logger.py +47 -45
- {mtcli-3.2.1 → mtcli-3.3.0.dev0}/mtcli/models/conf_model.py +1 -2
- {mtcli-3.2.1 → mtcli-3.3.0.dev0}/mtcli/models/signals_model.py +0 -2
- {mtcli-3.2.1 → mtcli-3.3.0.dev0}/mtcli/mt5_context.py +2 -1
- {mtcli-3.2.1 → mtcli-3.3.0.dev0}/mtcli/plugins/media_movel/models/model_media_movel.py +22 -25
- {mtcli-3.2.1 → mtcli-3.3.0.dev0}/mtcli/plugins/range_medio/command.py +1 -0
- {mtcli-3.2.1 → mtcli-3.3.0.dev0}/mtcli/views/close_view.py +1 -1
- {mtcli-3.2.1 → mtcli-3.3.0.dev0}/mtcli/views/high_view.py +1 -1
- {mtcli-3.2.1 → mtcli-3.3.0.dev0}/mtcli/views/low_view.py +1 -1
- {mtcli-3.2.1 → mtcli-3.3.0.dev0}/mtcli/views/open_view.py +1 -1
- {mtcli-3.2.1 → mtcli-3.3.0.dev0}/mtcli/views/ranges_view.py +1 -3
- {mtcli-3.2.1 → mtcli-3.3.0.dev0}/mtcli/views/vars_view.py +1 -8
- {mtcli-3.2.1 → mtcli-3.3.0.dev0}/mtcli/views/volumes_view.py +1 -2
- {mtcli-3.2.1 → mtcli-3.3.0.dev0}/pyproject.toml +28 -3
- mtcli-3.2.1/mtcli/plugins/agressao/__init__.py +0 -4
- mtcli-3.2.1/mtcli/plugins/agressao/command.py +0 -45
- mtcli-3.2.1/mtcli/plugins/agressao/models/__init__.py +0 -1
- mtcli-3.2.1/mtcli/plugins/agressao/models/model_agressao.py +0 -39
- mtcli-3.2.1/mtcli/plugins/agressao/views/__init__.py +0 -1
- mtcli-3.2.1/mtcli/plugins/agressao/views/view_agressao.py +0 -15
- mtcli-3.2.1/mtcli/plugins/volume_medio/conf.py +0 -1
- {mtcli-3.2.1 → mtcli-3.3.0.dev0}/LICENSE +0 -0
- {mtcli-3.2.1 → mtcli-3.3.0.dev0}/README.md +0 -0
- {mtcli-3.2.1 → mtcli-3.3.0.dev0}/mtcli/__init__.py +0 -0
- {mtcli-3.2.1 → mtcli-3.3.0.dev0}/mtcli/commands/__init__.py +0 -0
- {mtcli-3.2.1 → mtcli-3.3.0.dev0}/mtcli/data/__init__.py +0 -0
- {mtcli-3.2.1 → mtcli-3.3.0.dev0}/mtcli/data/base.py +0 -0
- {mtcli-3.2.1 → mtcli-3.3.0.dev0}/mtcli/data/csv.py +0 -0
- {mtcli-3.2.1 → mtcli-3.3.0.dev0}/mtcli/models/__init__.py +0 -0
- {mtcli-3.2.1 → mtcli-3.3.0.dev0}/mtcli/models/bar_model.py +0 -0
- {mtcli-3.2.1 → mtcli-3.3.0.dev0}/mtcli/models/bars_model.py +0 -0
- {mtcli-3.2.1 → mtcli-3.3.0.dev0}/mtcli/models/chart_model.py +0 -0
- {mtcli-3.2.1 → mtcli-3.3.0.dev0}/mtcli/models/consecutive_bars_model.py +0 -0
- {mtcli-3.2.1 → mtcli-3.3.0.dev0}/mtcli/models/rates_model.py +0 -0
- {mtcli-3.2.1 → mtcli-3.3.0.dev0}/mtcli/models/unconsecutive_bar_model.py +0 -0
- {mtcli-3.2.1 → mtcli-3.3.0.dev0}/mtcli/mt.py +0 -0
- {mtcli-3.2.1 → mtcli-3.3.0.dev0}/mtcli/plugin.py +0 -0
- {mtcli-3.2.1 → mtcli-3.3.0.dev0}/mtcli/plugins/__init__.py +0 -0
- {mtcli-3.2.1 → mtcli-3.3.0.dev0}/mtcli/plugins/media_movel/__init__.py +0 -0
- {mtcli-3.2.1 → mtcli-3.3.0.dev0}/mtcli/plugins/media_movel/command.py +0 -0
- {mtcli-3.2.1 → mtcli-3.3.0.dev0}/mtcli/plugins/media_movel/conf.py +0 -0
- {mtcli-3.2.1 → mtcli-3.3.0.dev0}/mtcli/plugins/media_movel/models/__init__.py +0 -0
- {mtcli-3.2.1 → mtcli-3.3.0.dev0}/mtcli/plugins/media_movel/tests/__init__.py +0 -0
- {mtcli-3.2.1 → mtcli-3.3.0.dev0}/mtcli/plugins/media_movel/tests/test_mm.py +0 -0
- {mtcli-3.2.1 → mtcli-3.3.0.dev0}/mtcli/plugins/media_movel/tests/test_model_media_movel.py +0 -0
- {mtcli-3.2.1 → mtcli-3.3.0.dev0}/mtcli/plugins/range_medio/__init__.py +0 -0
- {mtcli-3.2.1/mtcli/plugins/agressao → mtcli-3.3.0.dev0/mtcli/plugins/range_medio}/conf.py +0 -0
- {mtcli-3.2.1 → mtcli-3.3.0.dev0}/mtcli/plugins/range_medio/models/__init__.py +0 -0
- {mtcli-3.2.1 → mtcli-3.3.0.dev0}/mtcli/plugins/range_medio/models/average_range_model.py +0 -0
- {mtcli-3.2.1 → mtcli-3.3.0.dev0}/mtcli/plugins/range_medio/tests/__init__.py +0 -0
- {mtcli-3.2.1 → mtcli-3.3.0.dev0}/mtcli/plugins/range_medio/tests/test_rm.py +0 -0
- {mtcli-3.2.1 → mtcli-3.3.0.dev0}/mtcli/plugins/volume_medio/__init__.py +0 -0
- {mtcli-3.2.1 → mtcli-3.3.0.dev0}/mtcli/plugins/volume_medio/command.py +0 -0
- {mtcli-3.2.1/mtcli/plugins/range_medio → mtcli-3.3.0.dev0/mtcli/plugins/volume_medio}/conf.py +0 -0
- {mtcli-3.2.1 → mtcli-3.3.0.dev0}/mtcli/plugins/volume_medio/models/__init__.py +0 -0
- {mtcli-3.2.1 → mtcli-3.3.0.dev0}/mtcli/plugins/volume_medio/models/model_average_volume.py +0 -0
- {mtcli-3.2.1 → mtcli-3.3.0.dev0}/mtcli/plugins/volume_medio/tests/__init__.py +0 -0
- {mtcli-3.2.1 → mtcli-3.3.0.dev0}/mtcli/plugins/volume_medio/tests/test_vm.py +0 -0
- {mtcli-3.2.1 → mtcli-3.3.0.dev0}/mtcli/views/__init__.py +0 -0
- {mtcli-3.2.1 → mtcli-3.3.0.dev0}/mtcli/views/full_view.py +0 -0
- {mtcli-3.2.1 → mtcli-3.3.0.dev0}/mtcli/views/min_view.py +0 -0
- {mtcli-3.2.1 → mtcli-3.3.0.dev0}/mtcli/views/rates_view.py +0 -0
|
@@ -1,147 +1,147 @@
|
|
|
1
|
-
"""Exibe o gráfico de barras."""
|
|
2
|
-
|
|
3
|
-
import click
|
|
4
|
-
|
|
5
|
-
from mtcli.
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
from mtcli.
|
|
14
|
-
from mtcli.
|
|
15
|
-
from mtcli.views.
|
|
16
|
-
from mtcli.views.
|
|
17
|
-
from mtcli.
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
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)
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
if __name__ == "__main__":
|
|
147
|
-
bars()
|
|
1
|
+
"""Exibe o gráfico de barras."""
|
|
2
|
+
|
|
3
|
+
import click
|
|
4
|
+
|
|
5
|
+
from mtcli.conf import (
|
|
6
|
+
BARS,
|
|
7
|
+
DATE,
|
|
8
|
+
PERIOD,
|
|
9
|
+
TIMEFRAMES,
|
|
10
|
+
VIEW,
|
|
11
|
+
VOLUME,
|
|
12
|
+
)
|
|
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
|
|
25
|
+
|
|
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)
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
if __name__ == "__main__":
|
|
147
|
+
bars()
|
|
@@ -1,40 +1,42 @@
|
|
|
1
|
-
"""Comando logs para exibição dos logs."""
|
|
2
|
-
|
|
3
|
-
import os
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
@click.
|
|
11
|
-
@click.option("--
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
click.echo("
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
if
|
|
35
|
-
linhas = [
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
click.
|
|
1
|
+
"""Comando logs para exibição dos logs."""
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
|
|
5
|
+
import click
|
|
6
|
+
|
|
7
|
+
from mtcli.logger import setup_logger
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@click.command("logs", help="Exibe ou limpa os logs de execução do mtcli.")
|
|
11
|
+
@click.option("--clear", is_flag=True, help="Limpa o arquivo de log.")
|
|
12
|
+
@click.option("--tail", default=0, type=int, help="Mostra apenas as últimas N linhas.")
|
|
13
|
+
@click.option("--grep", default="", help="Filtra o log por uma palavra-chave.")
|
|
14
|
+
def logs(clear, tail, grep):
|
|
15
|
+
"""Exibe ou limpa os registros de log do mtcli."""
|
|
16
|
+
logger = setup_logger()
|
|
17
|
+
log_file = logger.handlers[0].baseFilename
|
|
18
|
+
|
|
19
|
+
if clear:
|
|
20
|
+
if os.path.exists(log_file):
|
|
21
|
+
open(log_file, "w", encoding="utf-8").close()
|
|
22
|
+
click.echo("Log limpo com sucesso.")
|
|
23
|
+
else:
|
|
24
|
+
click.echo("Nenhum log para limpar.")
|
|
25
|
+
return
|
|
26
|
+
|
|
27
|
+
if not os.path.exists(log_file):
|
|
28
|
+
click.echo("Nenhum log encontrado.")
|
|
29
|
+
return
|
|
30
|
+
|
|
31
|
+
with open(log_file, encoding="utf-8", errors="ignore") as f:
|
|
32
|
+
linhas = f.readlines()
|
|
33
|
+
|
|
34
|
+
if tail > 0:
|
|
35
|
+
linhas = linhas[-tail:]
|
|
36
|
+
if grep:
|
|
37
|
+
linhas = [linha for linha in linhas if grep.lower() in linha.lower()]
|
|
38
|
+
|
|
39
|
+
if not linhas:
|
|
40
|
+
click.echo("Nenhuma linha encontrada com os filtros aplicados.")
|
|
41
|
+
else:
|
|
42
|
+
click.echo_via_pager("".join(linhas))
|
|
@@ -1,101 +1,102 @@
|
|
|
1
|
-
import os
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
)
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
)
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
)
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
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
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
csv_path
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
"
|
|
82
|
-
"
|
|
83
|
-
"
|
|
84
|
-
"
|
|
85
|
-
"
|
|
86
|
-
"
|
|
87
|
-
"
|
|
88
|
-
"
|
|
89
|
-
"
|
|
90
|
-
"
|
|
91
|
-
"
|
|
92
|
-
"
|
|
93
|
-
"
|
|
94
|
-
"
|
|
95
|
-
"
|
|
96
|
-
"
|
|
97
|
-
"
|
|
98
|
-
"
|
|
99
|
-
"
|
|
100
|
-
"
|
|
101
|
-
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
import MetaTrader5 as mt5
|
|
4
|
+
|
|
5
|
+
from mtcli.conecta import conectar, shutdown
|
|
6
|
+
from mtcli.models.conf_model import ConfModel
|
|
7
|
+
|
|
8
|
+
config = ConfModel("mtcli.ini").carregar()
|
|
9
|
+
|
|
10
|
+
section = "DEFAULT"
|
|
11
|
+
symbol = os.getenv("SYMBOL", config[section].get("symbol", fallback="WIN$N"))
|
|
12
|
+
digitos = int(os.getenv("DIGITOS", config[section].getint("digitos", fallback=2)))
|
|
13
|
+
PERIOD = period = os.getenv("PERIOD", config[section].get("period", fallback="D1"))
|
|
14
|
+
BARS = periodos = count = int(
|
|
15
|
+
os.getenv("COUNT", config[section].getint("count", fallback=999))
|
|
16
|
+
)
|
|
17
|
+
VIEW = view = os.getenv("VIEW", config[section].get("view", fallback="ch"))
|
|
18
|
+
VOLUME = volume = os.getenv("VOLUME", config[section].get("volume", fallback="tick"))
|
|
19
|
+
DATE = date = os.getenv("DATE", config[section].get("date", fallback=""))
|
|
20
|
+
|
|
21
|
+
lateral = os.getenv("LATERAL", config[section].get("lateral", fallback="doji"))
|
|
22
|
+
alta = os.getenv("ALTA", config[section].get("alta", fallback="verde"))
|
|
23
|
+
baixa = os.getenv("BAIXA", config[section].get("baixa", fallback="vermelho"))
|
|
24
|
+
rompimento_alta = os.getenv(
|
|
25
|
+
"ROMPIMENTO_ALTA", config[section].get("rompimento_alta", fallback="c")
|
|
26
|
+
)
|
|
27
|
+
rompimento_baixa = os.getenv(
|
|
28
|
+
"ROMPIMENTO_BAIXA", config[section].get("rompimento_baixa", fallback="v")
|
|
29
|
+
)
|
|
30
|
+
percentual_rompimento = int(
|
|
31
|
+
os.getenv(
|
|
32
|
+
"PERCENTUAL_ROMPIMENTO",
|
|
33
|
+
config[section].getint("percentual_rompimento", fallback=50),
|
|
34
|
+
)
|
|
35
|
+
)
|
|
36
|
+
percentual_doji = int(
|
|
37
|
+
os.getenv("PERCENTUAL_DOJI", config[section].getint("percentual_doji", fallback=10))
|
|
38
|
+
)
|
|
39
|
+
up_bar = os.getenv("UP_BAR", config[section].get("up_bar", fallback="asc"))
|
|
40
|
+
down_bar = os.getenv("DOWN_BAR", config[section].get("down_bar", fallback="desc"))
|
|
41
|
+
inside_bar = os.getenv("INSIDE_BAR", config[section].get("inside_bar", fallback="ib"))
|
|
42
|
+
outside_bar = os.getenv(
|
|
43
|
+
"OUTSIDE_BAR", config[section].get("outside_bar", fallback="ob")
|
|
44
|
+
)
|
|
45
|
+
sombra_superior = os.getenv(
|
|
46
|
+
"SOMBRA_SUPERIOR", config[section].get("sombra_superior", fallback="top")
|
|
47
|
+
)
|
|
48
|
+
sombra_inferior = os.getenv(
|
|
49
|
+
"SOMBRA_INFERIOR", config[section].get("sombra_inferior", fallback="bottom")
|
|
50
|
+
)
|
|
51
|
+
data_source = dados = os.getenv("DADOS", config[section].get("dados", fallback="mt5"))
|
|
52
|
+
csv_path = mt5_pasta = os.getenv(
|
|
53
|
+
"MT5_PASTA", config[section].get("mt5_pasta", fallback="")
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def get_data_source():
|
|
58
|
+
from mtcli.data import CsvDataSource, MT5DataSource
|
|
59
|
+
|
|
60
|
+
if data_source.lower() == "csv":
|
|
61
|
+
return CsvDataSource()
|
|
62
|
+
elif data_source.lower() == "mt5":
|
|
63
|
+
return MT5DataSource()
|
|
64
|
+
else:
|
|
65
|
+
raise ValueError(f"Fonte de dados desconhecida: {data_source}")
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
if not csv_path:
|
|
69
|
+
conectar()
|
|
70
|
+
terminal_info = mt5.terminal_info()
|
|
71
|
+
if terminal_info is None:
|
|
72
|
+
raise RuntimeError("Não foi possível obter as informações do terminal.")
|
|
73
|
+
|
|
74
|
+
csv_path = terminal_info.data_path + "/MQL5/Files"
|
|
75
|
+
shutdown()
|
|
76
|
+
|
|
77
|
+
csv_path = csv_path.replace("\\", "/")
|
|
78
|
+
csv_path += "/"
|
|
79
|
+
|
|
80
|
+
TIMEFRAMES = timeframes = [
|
|
81
|
+
"mn1",
|
|
82
|
+
"w1",
|
|
83
|
+
"d1",
|
|
84
|
+
"h12",
|
|
85
|
+
"h8",
|
|
86
|
+
"h6",
|
|
87
|
+
"h4",
|
|
88
|
+
"h3",
|
|
89
|
+
"h2",
|
|
90
|
+
"h1",
|
|
91
|
+
"m30",
|
|
92
|
+
"m20",
|
|
93
|
+
"m15",
|
|
94
|
+
"m12",
|
|
95
|
+
"m10",
|
|
96
|
+
"m6",
|
|
97
|
+
"m5",
|
|
98
|
+
"m4",
|
|
99
|
+
"m3",
|
|
100
|
+
"m2",
|
|
101
|
+
"m1",
|
|
102
|
+
]
|
|
@@ -1,45 +1,47 @@
|
|
|
1
|
-
import logging
|
|
2
|
-
from logging.handlers import RotatingFileHandler
|
|
3
|
-
import os
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
os.
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
1
|
+
import logging
|
|
2
|
+
from logging.handlers import RotatingFileHandler
|
|
3
|
+
import os
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
base_dir = os.getenv("APPDATA", os.path.expanduser("~"))
|
|
7
|
+
LOG_DIR = os.path.join(base_dir, "mtcli", "logs")
|
|
8
|
+
os.makedirs(LOG_DIR, exist_ok=True)
|
|
9
|
+
LOG_FILE = os.path.join(LOG_DIR, "mtcli.log")
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def setup_logger(name: str = "mtcli") -> logging.Logger:
|
|
13
|
+
"""Configura logger rotativo com saída em arquivo e console.
|
|
14
|
+
|
|
15
|
+
- Escreve logs em ~/.mtcli/mtcli.log (máx. 2 MB, 3 backups).
|
|
16
|
+
- Mostra logs também no console (stdout), capturáveis via pytest/caplog.
|
|
17
|
+
- Evita duplicar handlers.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
logger = logging.getLogger(name)
|
|
21
|
+
logger.setLevel(logging.DEBUG)
|
|
22
|
+
|
|
23
|
+
formatter = logging.Formatter(
|
|
24
|
+
"%(asctime)s | %(levelname)-8s | %(name)s | %(message)s",
|
|
25
|
+
datefmt="%Y-%m-%d %H:%M:%S",
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
# === File handler rotativo ===
|
|
29
|
+
if not any(isinstance(h, RotatingFileHandler) for h in logger.handlers):
|
|
30
|
+
file_handler = RotatingFileHandler(LOG_FILE, maxBytes=2_000_000, backupCount=3)
|
|
31
|
+
file_handler.setFormatter(formatter)
|
|
32
|
+
logger.addHandler(file_handler)
|
|
33
|
+
|
|
34
|
+
# === Stream handler (console) ===
|
|
35
|
+
if not any(isinstance(h, logging.StreamHandler) for h in logger.handlers):
|
|
36
|
+
console_handler = logging.StreamHandler()
|
|
37
|
+
console_handler.setFormatter(formatter)
|
|
38
|
+
logger.addHandler(console_handler)
|
|
39
|
+
|
|
40
|
+
# Permite que pytest caplog capture logs
|
|
41
|
+
logger.propagate = True
|
|
42
|
+
|
|
43
|
+
return logger
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
# Inicializa logger padrão
|
|
47
|
+
log = setup_logger()
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"""Modelo de configurações."""
|
|
2
2
|
|
|
3
|
-
import os
|
|
4
3
|
import configparser
|
|
5
4
|
from configparser import MissingSectionHeaderError
|
|
5
|
+
import os
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
class ConfigFormatError(Exception):
|
|
@@ -10,7 +10,6 @@ class ConfigFormatError(Exception):
|
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
class ConfModel:
|
|
13
|
-
|
|
14
13
|
def __init__(self, configuracoes):
|
|
15
14
|
self.CONFIG_PATH = os.path.abspath(configuracoes)
|
|
16
15
|
|
|
@@ -4,8 +4,9 @@ Fornece o contexto 'mt5_conexao' para uso seguro em blocos with.
|
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
6
|
from contextlib import contextmanager
|
|
7
|
-
|
|
7
|
+
|
|
8
8
|
from mtcli.conecta import conectar, shutdown
|
|
9
|
+
from mtcli.logger import setup_logger
|
|
9
10
|
|
|
10
11
|
log = setup_logger()
|
|
11
12
|
|
|
@@ -1,25 +1,22 @@
|
|
|
1
|
-
"""Modulo da classe model da media movel."""
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
]
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
ema
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
ema
|
|
23
|
-
for price in self.closes[self.periodos :]:
|
|
24
|
-
ema.append(price * k + ema[-1] * (1 - k))
|
|
25
|
-
return ema
|
|
1
|
+
"""Modulo da classe model da media movel."""
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class MediaMovelModel:
|
|
5
|
+
def __init__(self, closes, periodos=14):
|
|
6
|
+
self.closes = [float(c) for c in closes]
|
|
7
|
+
self.periodos = periodos
|
|
8
|
+
|
|
9
|
+
def calcula_sma(self):
|
|
10
|
+
return [
|
|
11
|
+
sum(self.closes[i - self.periodos + 1 : i + 1]) / self.periodos
|
|
12
|
+
for i in range(self.periodos - 1, len(self.closes))
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
def calcula_ema(self):
|
|
16
|
+
ema = []
|
|
17
|
+
k = 2 / (self.periodos + 1)
|
|
18
|
+
sma = sum(self.closes[: self.periodos]) / self.periodos
|
|
19
|
+
ema.append(sma)
|
|
20
|
+
for price in self.closes[self.periodos :]:
|
|
21
|
+
ema.append(price * k + ema[-1] * (1 - k))
|
|
22
|
+
return ema
|
|
@@ -31,7 +31,7 @@ class CloseView:
|
|
|
31
31
|
data = bar.date if self.period in {"d1", "w1", "mn1"} else bar.time
|
|
32
32
|
sufixo = f" {data}"
|
|
33
33
|
|
|
34
|
-
linha = f"{prefixo}
|
|
34
|
+
linha = f"{prefixo}{bar.close:.{conf.digitos}f}{sufixo}"
|
|
35
35
|
views.append(linha)
|
|
36
36
|
|
|
37
37
|
return views
|
|
@@ -31,7 +31,7 @@ class HighView:
|
|
|
31
31
|
data = bar.date if self.period in {"d1", "w1", "mn1"} else bar.time
|
|
32
32
|
sufixo = f" {data}"
|
|
33
33
|
|
|
34
|
-
linha = f"{prefixo}
|
|
34
|
+
linha = f"{prefixo}{bar.high:.{conf.digitos}f}{sufixo}"
|
|
35
35
|
views.append(linha)
|
|
36
36
|
|
|
37
37
|
return views
|
|
@@ -31,7 +31,7 @@ class LowView:
|
|
|
31
31
|
data = bar.date if self.period in {"d1", "w1", "mn1"} else bar.time
|
|
32
32
|
sufixo = f" {data}"
|
|
33
33
|
|
|
34
|
-
linha = f"{prefixo}
|
|
34
|
+
linha = f"{prefixo}{bar.low:.{conf.digitos}f}{sufixo}"
|
|
35
35
|
views.append(linha)
|
|
36
36
|
|
|
37
37
|
return views
|
|
@@ -31,7 +31,7 @@ class OpenView:
|
|
|
31
31
|
data = bar.date if self.period in {"d1", "w1", "mn1"} else bar.time
|
|
32
32
|
sufixo = f" {data}"
|
|
33
33
|
|
|
34
|
-
linha = f"{prefixo}
|
|
34
|
+
linha = f"{prefixo}{bar.open:.{conf.digitos}f}{sufixo}"
|
|
35
35
|
views.append(linha)
|
|
36
36
|
|
|
37
37
|
return views
|
|
@@ -34,9 +34,7 @@ class RangesView:
|
|
|
34
34
|
sufixo = f" {data}"
|
|
35
35
|
|
|
36
36
|
linha = (
|
|
37
|
-
f"{prefixo}{sequencia} "
|
|
38
|
-
f"{bar.trend} {bar.range:.{conf.digitos}f}"
|
|
39
|
-
f"{sufixo}"
|
|
37
|
+
f"{prefixo}{sequencia} {bar.trend} {bar.range:.{conf.digitos}f}{sufixo}"
|
|
40
38
|
)
|
|
41
39
|
views.append(linha.upper())
|
|
42
40
|
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
"""Módulo da classe da view de variações percentuais."""
|
|
2
2
|
|
|
3
|
-
from mtcli import conf
|
|
4
3
|
from mtcli.models.chart_model import ChartModel
|
|
5
4
|
|
|
6
5
|
|
|
@@ -41,13 +40,7 @@ class VarsView:
|
|
|
41
40
|
data = bar.date if self.period in {"d1", "w1", "mn1"} else bar.time
|
|
42
41
|
sufixo = f" {data}"
|
|
43
42
|
|
|
44
|
-
linha =
|
|
45
|
-
f"{prefixo}"
|
|
46
|
-
f"{var_max:.2f}% "
|
|
47
|
-
f"{var_min:.2f}% "
|
|
48
|
-
f"{var_fech:.2f}%"
|
|
49
|
-
f"{sufixo}"
|
|
50
|
-
)
|
|
43
|
+
linha = f"{prefixo}{var_max:.2f}% {var_min:.2f}% {var_fech:.2f}%{sufixo}"
|
|
51
44
|
views.append(linha.upper())
|
|
52
45
|
|
|
53
46
|
return views
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
"""Módulo da classe da view de volumes."""
|
|
2
2
|
|
|
3
|
-
from mtcli import conf
|
|
4
3
|
from mtcli.models.chart_model import ChartModel
|
|
5
4
|
|
|
6
5
|
|
|
@@ -46,7 +45,7 @@ class VolumesView:
|
|
|
46
45
|
data = bar.date if self.period in {"d1", "w1", "mn1"} else bar.time
|
|
47
46
|
sufixo = f" {data}"
|
|
48
47
|
|
|
49
|
-
linha = f"{prefixo}{sequencia} {sequencia_volume} {volume}
|
|
48
|
+
linha = f"{prefixo}{sequencia} {sequencia_volume} {volume}{sufixo}"
|
|
50
49
|
views.append(linha.upper())
|
|
51
50
|
|
|
52
51
|
return views
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "mtcli"
|
|
3
|
-
version = "3.
|
|
3
|
+
version = "3.3.0.dev0"
|
|
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"}
|
|
@@ -58,7 +58,32 @@ pymdown-extensions = "^10.16.1"
|
|
|
58
58
|
pytest = "^8.4.2"
|
|
59
59
|
pytest-env = "^1.1.5"
|
|
60
60
|
pytest-cov = "^6.3.0"
|
|
61
|
-
black = "^25.1.0"
|
|
62
|
-
isort = "^6.0.1"
|
|
63
61
|
pydocstyle = "^6.3.0"
|
|
62
|
+
ruff = "^0.14.1"
|
|
63
|
+
pytest-mock = "^3.15.1"
|
|
64
64
|
|
|
65
|
+
[tool.ruff]
|
|
66
|
+
line-length = 88
|
|
67
|
+
target-version = "py311"
|
|
68
|
+
|
|
69
|
+
[tool.ruff.lint]
|
|
70
|
+
select = [
|
|
71
|
+
"E", # Estilo
|
|
72
|
+
"F", # Lógica
|
|
73
|
+
"B", # Boas práticas
|
|
74
|
+
"I", # Imports
|
|
75
|
+
"UP", # Upgrade
|
|
76
|
+
"N", # Naming
|
|
77
|
+
]
|
|
78
|
+
ignore = ["E501"]
|
|
79
|
+
|
|
80
|
+
[tool.ruff.lint.isort]
|
|
81
|
+
known-first-party = ["mtcli"]
|
|
82
|
+
combine-as-imports = true
|
|
83
|
+
force-sort-within-sections = true
|
|
84
|
+
|
|
85
|
+
[tool.ruff.format]
|
|
86
|
+
quote-style = "double"
|
|
87
|
+
indent-style = "space"
|
|
88
|
+
line-ending = "auto"
|
|
89
|
+
skip-magic-trailing-comma = false
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
"""Exibe o saldo agressor."""
|
|
2
|
-
|
|
3
|
-
import click
|
|
4
|
-
|
|
5
|
-
from mtcli.models import model_bars, model_rates
|
|
6
|
-
|
|
7
|
-
from . import conf
|
|
8
|
-
from .models import model_agressao
|
|
9
|
-
from .views import view_agressao
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
@click.command()
|
|
13
|
-
@click.argument("symbol")
|
|
14
|
-
@click.option(
|
|
15
|
-
"--period",
|
|
16
|
-
"-p",
|
|
17
|
-
type=click.Choice(conf.timeframes, case_sensitive=False),
|
|
18
|
-
default="d1",
|
|
19
|
-
help="Tempo grafico, default D1.",
|
|
20
|
-
)
|
|
21
|
-
@click.option(
|
|
22
|
-
"--count", "-c", type=int, default=20, help="Quantidade de barras, default 20."
|
|
23
|
-
)
|
|
24
|
-
@click.option(
|
|
25
|
-
"--volume",
|
|
26
|
-
"-vo",
|
|
27
|
-
type=click.Choice(["tick", "real"], case_sensitive=False),
|
|
28
|
-
default="tick",
|
|
29
|
-
help="Tipo de volume, default tick.",
|
|
30
|
-
)
|
|
31
|
-
def sa(symbol, period, count, volume):
|
|
32
|
-
"""Exibe o saldo da agressão."""
|
|
33
|
-
period = period.lower()
|
|
34
|
-
rates = model_rates.RatesModel(symbol, period)
|
|
35
|
-
rates = rates.lista
|
|
36
|
-
bars = model_bars.BarsModel(rates)
|
|
37
|
-
bars = bars.lista
|
|
38
|
-
agressao = model_agressao.AgressaoModel(bars, volume, count)
|
|
39
|
-
saldo_agressao = agressao.get_saldo()
|
|
40
|
-
view = view_agressao.AgressaoView(saldo_agressao)
|
|
41
|
-
click.echo(view.view())
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
if __name__ == "__main__":
|
|
45
|
-
sa()
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
from . import model_agressao
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
"""Módulo da classe model para saldo da agressão."""
|
|
2
|
-
|
|
3
|
-
from mtcli import conf
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
class AgressaoModel:
|
|
7
|
-
"""Classe model do saldo da agressao."""
|
|
8
|
-
|
|
9
|
-
def __init__(self, bars, type="tick", count=5):
|
|
10
|
-
"""Construtor do saldo da agressão."""
|
|
11
|
-
self.bars = bars[-count:]
|
|
12
|
-
self.type = type
|
|
13
|
-
self.count = count
|
|
14
|
-
self.volume_comprador = self.__get_volume_comprador()
|
|
15
|
-
self.volume_vendedor = self.__get_volume_vendedor()
|
|
16
|
-
|
|
17
|
-
def __get_volume_comprador(self):
|
|
18
|
-
"""Obtem o volume comprador."""
|
|
19
|
-
volume = 0
|
|
20
|
-
for bar in self.bars:
|
|
21
|
-
if (bar.trend == conf.alta and bar.body > 50) or bar.bottom > 50:
|
|
22
|
-
volume += bar.volume if self.type == "tick" else bar.volume_real
|
|
23
|
-
return volume
|
|
24
|
-
|
|
25
|
-
def __get_volume_vendedor(self):
|
|
26
|
-
"""Obtem o volume vendedor."""
|
|
27
|
-
volume = 0
|
|
28
|
-
for bar in self.bars:
|
|
29
|
-
if (bar.trend == conf.baixa and bar.body > 50) or bar.top > 50:
|
|
30
|
-
volume += bar.volume if self.type == "tick" else bar.volume_real
|
|
31
|
-
return volume
|
|
32
|
-
|
|
33
|
-
def get_saldo(self):
|
|
34
|
-
"""Calcula o saldo da agressão."""
|
|
35
|
-
return (
|
|
36
|
-
self.volume_comprador,
|
|
37
|
-
self.volume_vendedor,
|
|
38
|
-
self.volume_comprador - self.volume_vendedor,
|
|
39
|
-
)
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
from . import view_agressao
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
"""Módulo da classe da view saldo da agressão."""
|
|
2
|
-
|
|
3
|
-
from mtcli import conf
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
class AgressaoView:
|
|
7
|
-
"""Classe da view do saldo da agressao."""
|
|
8
|
-
|
|
9
|
-
def __init__(self, saldo_agressao):
|
|
10
|
-
"""Construtor da view saldo da agressao."""
|
|
11
|
-
self.agressao = saldo_agressao
|
|
12
|
-
|
|
13
|
-
def view(self):
|
|
14
|
-
"""View do saldo da agressão."""
|
|
15
|
-
return "%i %i %i" % (self.agressao[0], self.agressao[1], self.agressao[2])
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
from mtcli.conf import *
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mtcli-3.2.1/mtcli/plugins/range_medio → mtcli-3.3.0.dev0/mtcli/plugins/volume_medio}/conf.py
RENAMED
|
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
|