mtcli 3.6.0.dev1__py3-none-any.whl → 3.7.0.dev0__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 +34 -34
- mtcli/commands/conf.py +44 -0
- mtcli/conf.py +160 -126
- mtcli/config_registre.py +41 -0
- mtcli/data/csv.py +31 -31
- mtcli/logger.py +102 -13
- mtcli/models/consecutive_bars_model.py +77 -77
- mtcli/models/rates_model.py +41 -41
- mtcli/models/unconsecutive_bar_model.py +67 -67
- mtcli/plugin.py +18 -18
- mtcli/plugin_loader.py +47 -63
- mtcli/plugin_manager.py +27 -0
- mtcli/plugins/media_movel/__init__.py +5 -5
- mtcli/plugins/media_movel/tests/test_mm.py +13 -13
- mtcli/plugins/range_medio/cli.py +32 -32
- mtcli/plugins/range_medio/models/average_range_model.py +29 -29
- mtcli/plugins/range_medio/tests/test_rm.py +11 -11
- mtcli/plugins/volume_medio/cli.py +41 -41
- mtcli/plugins/volume_medio/models/model_average_volume.py +31 -31
- mtcli/plugins/volume_medio/tests/test_vm.py +21 -21
- mtcli/views/close_view.py +37 -37
- mtcli/views/full_view.py +65 -65
- mtcli/views/high_view.py +37 -37
- mtcli/views/low_view.py +37 -37
- mtcli/views/min_view.py +42 -42
- mtcli/views/open_view.py +37 -37
- mtcli/views/ranges_view.py +41 -41
- mtcli/views/rates_view.py +41 -41
- {mtcli-3.6.0.dev1.dist-info → mtcli-3.7.0.dev0.dist-info}/METADATA +1 -1
- {mtcli-3.6.0.dev1.dist-info → mtcli-3.7.0.dev0.dist-info}/RECORD +33 -30
- {mtcli-3.6.0.dev1.dist-info → mtcli-3.7.0.dev0.dist-info}/WHEEL +0 -0
- {mtcli-3.6.0.dev1.dist-info → mtcli-3.7.0.dev0.dist-info}/entry_points.txt +0 -0
- {mtcli-3.6.0.dev1.dist-info → mtcli-3.7.0.dev0.dist-info}/licenses/LICENSE +0 -0
mtcli/cli.py
CHANGED
|
@@ -1,34 +1,34 @@
|
|
|
1
|
-
"""
|
|
2
|
-
CLI principal do mtcli.
|
|
3
|
-
|
|
4
|
-
Este módulo define o grupo principal `mt`
|
|
5
|
-
e inicializa o carregamento de plugins.
|
|
6
|
-
"""
|
|
7
|
-
|
|
8
|
-
import click
|
|
9
|
-
|
|
10
|
-
from mtcli.plugin_loader import load_plugins
|
|
11
|
-
from .commands.bars import bars
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
@click.group(context_settings={"max_content_width": 120})
|
|
15
|
-
@click.version_option(package_name="mtcli")
|
|
16
|
-
def mt():
|
|
17
|
-
"""
|
|
18
|
-
CLI principal do mtcli.
|
|
19
|
-
|
|
20
|
-
Exibe gráficos e informações de mercado
|
|
21
|
-
em formato textual compatível com leitores de tela.
|
|
22
|
-
"""
|
|
23
|
-
pass
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
mt.add_command(bars, name="bars")
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
# Carrega plugins automaticamente
|
|
30
|
-
load_plugins(mt)
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
if __name__ == "__main__":
|
|
34
|
-
mt()
|
|
1
|
+
"""
|
|
2
|
+
CLI principal do mtcli.
|
|
3
|
+
|
|
4
|
+
Este módulo define o grupo principal `mt`
|
|
5
|
+
e inicializa o carregamento de plugins.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import click
|
|
9
|
+
|
|
10
|
+
from mtcli.plugin_loader import load_plugins
|
|
11
|
+
from .commands.bars import bars
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@click.group(context_settings={"max_content_width": 120})
|
|
15
|
+
@click.version_option(package_name="mtcli")
|
|
16
|
+
def mt():
|
|
17
|
+
"""
|
|
18
|
+
CLI principal do mtcli.
|
|
19
|
+
|
|
20
|
+
Exibe gráficos e informações de mercado
|
|
21
|
+
em formato textual compatível com leitores de tela.
|
|
22
|
+
"""
|
|
23
|
+
pass
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
mt.add_command(bars, name="bars")
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
# Carrega plugins automaticamente
|
|
30
|
+
load_plugins(mt)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
if __name__ == "__main__":
|
|
34
|
+
mt()
|
mtcli/commands/conf.py
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Comando para exibir configurações disponíveis.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import click
|
|
6
|
+
|
|
7
|
+
from mtcli.config_registry import registry
|
|
8
|
+
from mtcli.conf import conf
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@click.command()
|
|
12
|
+
@click.argument("section", required=False)
|
|
13
|
+
def conf_cmd(section):
|
|
14
|
+
"""
|
|
15
|
+
Exibe configurações disponíveis.
|
|
16
|
+
|
|
17
|
+
Exemplos:
|
|
18
|
+
|
|
19
|
+
mt conf
|
|
20
|
+
mt conf renko
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
if section:
|
|
24
|
+
options = registry.get_section(section)
|
|
25
|
+
else:
|
|
26
|
+
options = registry.get_all()
|
|
27
|
+
|
|
28
|
+
if not options:
|
|
29
|
+
click.echo("Nenhuma configuração registrada.")
|
|
30
|
+
return
|
|
31
|
+
|
|
32
|
+
for opt in options:
|
|
33
|
+
|
|
34
|
+
value = conf.get(opt.name, section=opt.section, default=opt.default)
|
|
35
|
+
|
|
36
|
+
click.echo(
|
|
37
|
+
f"{opt.section}.{opt.name} = {value} "
|
|
38
|
+
f"(default={opt.default})"
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
if opt.description:
|
|
42
|
+
click.echo(f" {opt.description}")
|
|
43
|
+
|
|
44
|
+
click.echo()
|
mtcli/conf.py
CHANGED
|
@@ -1,19 +1,18 @@
|
|
|
1
1
|
"""
|
|
2
|
-
|
|
2
|
+
Sistema central de configuração do mtcli.
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
Fornece leitura de configuração a partir de:
|
|
5
5
|
|
|
6
6
|
1. Variáveis de ambiente
|
|
7
7
|
2. Arquivo mtcli.ini
|
|
8
|
+
3. Valores default
|
|
8
9
|
|
|
9
|
-
|
|
10
|
+
Também oferece utilidades usadas por plugins como:
|
|
10
11
|
|
|
11
|
-
|
|
12
|
-
|
|
12
|
+
- descoberta do diretório MQL5/Files
|
|
13
|
+
- seleção da fonte de dados (CSV ou MT5)
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
efeitos colaterais durante a importação do módulo (import side effects),
|
|
16
|
-
facilitando testes automatizados e execução em ambientes CI/CD.
|
|
15
|
+
Plugins devem acessar a configuração através do objeto global `conf`.
|
|
17
16
|
"""
|
|
18
17
|
|
|
19
18
|
import os
|
|
@@ -23,170 +22,147 @@ import MetaTrader5 as mt5
|
|
|
23
22
|
|
|
24
23
|
from mtcli.mt5_context import mt5_conexao
|
|
25
24
|
|
|
26
|
-
# ---------------------------------------------------------
|
|
27
|
-
# Carregamento do arquivo de configuração
|
|
28
|
-
# ---------------------------------------------------------
|
|
29
25
|
|
|
30
|
-
|
|
31
|
-
|
|
26
|
+
class Config:
|
|
27
|
+
"""
|
|
28
|
+
Gerenciador central de configurações do mtcli.
|
|
29
|
+
"""
|
|
32
30
|
|
|
33
|
-
|
|
34
|
-
config.
|
|
31
|
+
def __init__(self, filename="mtcli.ini"):
|
|
32
|
+
self.config = configparser.ConfigParser()
|
|
33
|
+
self.config.read(filename)
|
|
35
34
|
|
|
35
|
+
# ---------------------------------------------------------
|
|
36
|
+
# leitura de valores
|
|
37
|
+
# ---------------------------------------------------------
|
|
36
38
|
|
|
37
|
-
def
|
|
38
|
-
|
|
39
|
-
|
|
39
|
+
def get(self, key, section="DEFAULT", cast=None, default=None):
|
|
40
|
+
"""
|
|
41
|
+
Retorna um valor de configuração.
|
|
40
42
|
|
|
41
|
-
|
|
42
|
-
1. Variável de ambiente
|
|
43
|
-
2. Arquivo mtcli.ini
|
|
44
|
-
3. Valor fallback
|
|
43
|
+
Prioridade:
|
|
45
44
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
45
|
+
1. Variável de ambiente SECTION_KEY
|
|
46
|
+
2. Variável de ambiente KEY
|
|
47
|
+
3. mtcli.ini [section]
|
|
48
|
+
4. mtcli.ini [DEFAULT]
|
|
49
|
+
5. default
|
|
50
50
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
if value is None:
|
|
57
|
-
try:
|
|
58
|
-
if cast == int:
|
|
59
|
-
value = config.getint(SECTION, key, fallback=fallback)
|
|
60
|
-
elif cast == float:
|
|
61
|
-
value = config.getfloat(SECTION, key, fallback=fallback)
|
|
62
|
-
else:
|
|
63
|
-
value = config.get(SECTION, key, fallback=fallback)
|
|
64
|
-
except (configparser.NoOptionError, ValueError):
|
|
65
|
-
value = fallback
|
|
66
|
-
else:
|
|
67
|
-
if cast:
|
|
68
|
-
try:
|
|
69
|
-
value = cast(value)
|
|
70
|
-
except ValueError:
|
|
71
|
-
value = fallback
|
|
51
|
+
Args:
|
|
52
|
+
key (str)
|
|
53
|
+
section (str)
|
|
54
|
+
cast (type | None)
|
|
55
|
+
default (Any)
|
|
72
56
|
|
|
73
|
-
|
|
57
|
+
Returns:
|
|
58
|
+
Any
|
|
59
|
+
"""
|
|
74
60
|
|
|
61
|
+
env_key = f"{section.upper()}_{key.upper()}"
|
|
75
62
|
|
|
76
|
-
|
|
77
|
-
# Configurações gerais
|
|
78
|
-
# ---------------------------------------------------------
|
|
63
|
+
value = os.getenv(env_key) or os.getenv(key.upper())
|
|
79
64
|
|
|
80
|
-
|
|
81
|
-
DIGITOS = get_config_value("digitos", cast=int, fallback=2)
|
|
82
|
-
PERIOD = get_config_value("period", fallback="D1")
|
|
83
|
-
BARS = get_config_value("count", cast=int, fallback=999)
|
|
65
|
+
if value is None:
|
|
84
66
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
DATE = get_config_value("date", fallback="")
|
|
67
|
+
if self.config.has_option(section, key):
|
|
68
|
+
value = self.config.get(section, key)
|
|
88
69
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
# ---------------------------------------------------------
|
|
70
|
+
elif self.config.has_option("DEFAULT", key):
|
|
71
|
+
value = self.config.get("DEFAULT", key)
|
|
92
72
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
BAIXA = get_config_value("baixa", fallback="vermelho")
|
|
73
|
+
else:
|
|
74
|
+
value = default
|
|
96
75
|
|
|
97
|
-
|
|
98
|
-
ROMPIMENTO_BAIXA = get_config_value("rompimento_baixa", fallback="v")
|
|
76
|
+
if cast and value is not None:
|
|
99
77
|
|
|
100
|
-
|
|
101
|
-
"percentual_rompimento", cast=int, fallback=50
|
|
102
|
-
)
|
|
78
|
+
try:
|
|
103
79
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
)
|
|
80
|
+
if cast is bool:
|
|
81
|
+
value = str(value).lower() in ("1", "true", "yes")
|
|
107
82
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
# ---------------------------------------------------------
|
|
83
|
+
else:
|
|
84
|
+
value = cast(value)
|
|
111
85
|
|
|
112
|
-
|
|
113
|
-
|
|
86
|
+
except ValueError:
|
|
87
|
+
value = default
|
|
114
88
|
|
|
115
|
-
|
|
116
|
-
OUTSIDE_BAR = get_config_value("outside_bar", fallback="ob")
|
|
89
|
+
return value
|
|
117
90
|
|
|
118
|
-
|
|
119
|
-
|
|
91
|
+
# ---------------------------------------------------------
|
|
92
|
+
# seção helper
|
|
93
|
+
# ---------------------------------------------------------
|
|
120
94
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
95
|
+
def section(self, section):
|
|
96
|
+
"""
|
|
97
|
+
Retorna um helper para acessar uma seção específica.
|
|
98
|
+
"""
|
|
124
99
|
|
|
125
|
-
|
|
100
|
+
class Section:
|
|
126
101
|
|
|
127
|
-
|
|
128
|
-
|
|
102
|
+
def __init__(self, parent, section):
|
|
103
|
+
self.parent = parent
|
|
104
|
+
self.section = section
|
|
129
105
|
|
|
106
|
+
def get(self, key, cast=None, default=None):
|
|
107
|
+
return self.parent.get(key, self.section, cast, default)
|
|
130
108
|
|
|
131
|
-
|
|
132
|
-
"""
|
|
133
|
-
Retorna o caminho da pasta de arquivos do MT5 ou CSV.
|
|
109
|
+
return Section(self, section)
|
|
134
110
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
111
|
+
# ---------------------------------------------------------
|
|
112
|
+
# caminho MT5
|
|
113
|
+
# ---------------------------------------------------------
|
|
114
|
+
|
|
115
|
+
def get_csv_path(self):
|
|
116
|
+
"""
|
|
117
|
+
Retorna o caminho da pasta MQL5/Files.
|
|
118
|
+
"""
|
|
119
|
+
|
|
120
|
+
path = self.get("mt5_pasta")
|
|
121
|
+
|
|
122
|
+
if path:
|
|
123
|
+
return os.path.normpath(path) + os.sep
|
|
138
124
|
|
|
139
|
-
Returns:
|
|
140
|
-
str: caminho normalizado da pasta de arquivos.
|
|
141
|
-
"""
|
|
142
|
-
if _INITIAL_CSV_PATH:
|
|
143
|
-
path = _INITIAL_CSV_PATH
|
|
144
|
-
else:
|
|
145
125
|
with mt5_conexao():
|
|
146
|
-
terminal_info = mt5.terminal_info()
|
|
147
126
|
|
|
148
|
-
|
|
127
|
+
info = mt5.terminal_info()
|
|
128
|
+
|
|
129
|
+
if info is None:
|
|
149
130
|
raise RuntimeError(
|
|
150
|
-
"Não foi possível obter
|
|
131
|
+
"Não foi possível obter informações do terminal MT5."
|
|
151
132
|
)
|
|
152
133
|
|
|
153
|
-
path = os.path.join(
|
|
154
|
-
|
|
155
|
-
return os.path.normpath(path) + os.sep
|
|
134
|
+
path = os.path.join(info.data_path, "MQL5", "Files")
|
|
156
135
|
|
|
136
|
+
return os.path.normpath(path) + os.sep
|
|
157
137
|
|
|
158
|
-
# ---------------------------------------------------------
|
|
159
|
-
#
|
|
160
|
-
# ---------------------------------------------------------
|
|
138
|
+
# ---------------------------------------------------------
|
|
139
|
+
# data source
|
|
140
|
+
# ---------------------------------------------------------
|
|
161
141
|
|
|
162
|
-
def get_data_source(source=None):
|
|
163
|
-
|
|
164
|
-
|
|
142
|
+
def get_data_source(self, source=None):
|
|
143
|
+
"""
|
|
144
|
+
Retorna a fonte de dados configurada.
|
|
145
|
+
"""
|
|
165
146
|
|
|
166
|
-
|
|
167
|
-
source (str | None): sobrescreve DATA_SOURCE se fornecido.
|
|
147
|
+
from mtcli.data import CsvDataSource, MT5DataSource
|
|
168
148
|
|
|
169
|
-
|
|
170
|
-
CsvDataSource | MT5DataSource
|
|
149
|
+
src = (source or self.get("dados", default="mt5")).lower()
|
|
171
150
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
"""
|
|
175
|
-
from mtcli.data import CsvDataSource, MT5DataSource
|
|
151
|
+
if src == "csv":
|
|
152
|
+
return CsvDataSource()
|
|
176
153
|
|
|
177
|
-
|
|
154
|
+
if src == "mt5":
|
|
155
|
+
return MT5DataSource()
|
|
178
156
|
|
|
179
|
-
|
|
180
|
-
return CsvDataSource()
|
|
157
|
+
raise ValueError(f"Fonte de dados desconhecida: {src}")
|
|
181
158
|
|
|
182
|
-
if src == "mt5":
|
|
183
|
-
return MT5DataSource()
|
|
184
159
|
|
|
185
|
-
|
|
160
|
+
# instância global usada por todo o sistema
|
|
161
|
+
conf = Config()
|
|
186
162
|
|
|
187
163
|
|
|
188
164
|
# ---------------------------------------------------------
|
|
189
|
-
#
|
|
165
|
+
# timeframes suportados
|
|
190
166
|
# ---------------------------------------------------------
|
|
191
167
|
|
|
192
168
|
_HOURS = [12, 8, 6, 4, 3, 2, 1]
|
|
@@ -197,3 +173,61 @@ TIMEFRAMES = (
|
|
|
197
173
|
+ [f"h{i}" for i in _HOURS]
|
|
198
174
|
+ [f"m{i}" for i in _MINUTES]
|
|
199
175
|
)
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
# ---------------------------------------------------------
|
|
179
|
+
# Configurações gerais
|
|
180
|
+
# ---------------------------------------------------------
|
|
181
|
+
|
|
182
|
+
SYMBOL = conf.get("symbol", default="WIN$N")
|
|
183
|
+
DIGITOS = conf.get("digitos", cast=int, default=2)
|
|
184
|
+
PERIOD = conf.get("period", default="D1")
|
|
185
|
+
BARS = conf.get("count", cast=int, default=999)
|
|
186
|
+
|
|
187
|
+
VIEW = conf.get("view", default="ch")
|
|
188
|
+
VOLUME = conf.get("volume", default="tick")
|
|
189
|
+
DATE = conf.get("date", default="")
|
|
190
|
+
|
|
191
|
+
# ---------------------------------------------------------
|
|
192
|
+
# Configurações de leitura de candles
|
|
193
|
+
# ---------------------------------------------------------
|
|
194
|
+
|
|
195
|
+
LATERAL = conf.get("lateral", default="doji")
|
|
196
|
+
ALTA = conf.get("alta", default="verde")
|
|
197
|
+
BAIXA = conf.get("baixa", default="vermelho")
|
|
198
|
+
|
|
199
|
+
ROMPIMENTO_ALTA = conf.get("rompimento_alta", default="c")
|
|
200
|
+
ROMPIMENTO_BAIXA = conf.get("rompimento_baixa", default="v")
|
|
201
|
+
|
|
202
|
+
PERCENTUAL_ROMPIMENTO = conf.get(
|
|
203
|
+
"percentual_rompimento", cast=int, default=50
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
PERCENTUAL_DOJI = conf.get(
|
|
207
|
+
"percentual_doji", cast=int, default=10
|
|
208
|
+
)
|
|
209
|
+
|
|
210
|
+
# ---------------------------------------------------------
|
|
211
|
+
# Configurações de padrões de barra
|
|
212
|
+
# ---------------------------------------------------------
|
|
213
|
+
|
|
214
|
+
UP_BAR = conf.get("up_bar", default="asc")
|
|
215
|
+
DOWN_BAR = conf.get("down_bar", default="desc")
|
|
216
|
+
|
|
217
|
+
INSIDE_BAR = conf.get("inside_bar", default="ib")
|
|
218
|
+
OUTSIDE_BAR = conf.get("outside_bar", default="ob")
|
|
219
|
+
|
|
220
|
+
SOMBRA_SUPERIOR = conf.get("sombra_superior", default="top")
|
|
221
|
+
SOMBRA_INFERIOR = conf.get("sombra_inferior", default="bottom")
|
|
222
|
+
|
|
223
|
+
# ---------------------------------------------------------
|
|
224
|
+
# Fonte de dados
|
|
225
|
+
# ---------------------------------------------------------
|
|
226
|
+
|
|
227
|
+
DATA_SOURCE = conf.get_data_source()
|
|
228
|
+
|
|
229
|
+
# ---------------------------------------------------------
|
|
230
|
+
# caminho inicial do CSV (pode vir do ini/env)
|
|
231
|
+
# ---------------------------------------------------------
|
|
232
|
+
|
|
233
|
+
_INITIAL_CSV_PATH = conf.get_csv_path()
|
mtcli/config_registre.py
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Registry de configurações do mtcli.
|
|
3
|
+
|
|
4
|
+
Plugins podem registrar suas opções de configuração aqui
|
|
5
|
+
para permitir descoberta automática via CLI.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class ConfigOption:
|
|
10
|
+
"""
|
|
11
|
+
Representa uma opção de configuração registrada.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
def __init__(self, section, name, type=str, default=None, description=""):
|
|
15
|
+
self.section = section
|
|
16
|
+
self.name = name
|
|
17
|
+
self.type = type
|
|
18
|
+
self.default = default
|
|
19
|
+
self.description = description
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class ConfigRegistry:
|
|
23
|
+
"""
|
|
24
|
+
Registro central de opções de configuração.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
def __init__(self):
|
|
28
|
+
self._options = []
|
|
29
|
+
|
|
30
|
+
def register(self, section, name, type=str, default=None, description=""):
|
|
31
|
+
option = ConfigOption(section, name, type, default, description)
|
|
32
|
+
self._options.append(option)
|
|
33
|
+
|
|
34
|
+
def get_all(self):
|
|
35
|
+
return self._options
|
|
36
|
+
|
|
37
|
+
def get_section(self, section):
|
|
38
|
+
return [o for o in self._options if o.section == section]
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
registry = ConfigRegistry()
|
mtcli/data/csv.py
CHANGED
|
@@ -1,31 +1,31 @@
|
|
|
1
|
-
"""Módulo fonte de dados via CSV."""
|
|
2
|
-
|
|
3
|
-
import csv
|
|
4
|
-
import os
|
|
5
|
-
|
|
6
|
-
from mtcli import conf
|
|
7
|
-
from mtcli.logger import setup_logger
|
|
8
|
-
|
|
9
|
-
from .base import DataSourceBase
|
|
10
|
-
|
|
11
|
-
logger = setup_logger()
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
class CsvDataSource(DataSourceBase):
|
|
15
|
-
"""Fonte de dados via CSV."""
|
|
16
|
-
|
|
17
|
-
def get_data(self, symbol, period, count=100):
|
|
18
|
-
"""Retorna dados CSV em uma lista de lista."""
|
|
19
|
-
file_path = os.path.join(conf._INITIAL_CSV_PATH, f"{symbol}{period}.csv")
|
|
20
|
-
logger.info(f"Iniciando coleta de dados via CSV: {file_path}.")
|
|
21
|
-
csv_data = []
|
|
22
|
-
try:
|
|
23
|
-
with open(file_path, encoding="utf-16", newline="") as f:
|
|
24
|
-
lines = csv.reader(f, delimiter=",", quotechar="'")
|
|
25
|
-
for line in lines:
|
|
26
|
-
csv_data.append(line)
|
|
27
|
-
except:
|
|
28
|
-
logger.warning(f"Arquivo {file_path} não encontrado.")
|
|
29
|
-
print("Arquivo %s nao encontrado! Tente novamente" % file_path)
|
|
30
|
-
logger.info("Coleta de dados via CSV finalizada.")
|
|
31
|
-
return csv_data
|
|
1
|
+
"""Módulo fonte de dados via CSV."""
|
|
2
|
+
|
|
3
|
+
import csv
|
|
4
|
+
import os
|
|
5
|
+
|
|
6
|
+
from mtcli import conf
|
|
7
|
+
from mtcli.logger import setup_logger
|
|
8
|
+
|
|
9
|
+
from .base import DataSourceBase
|
|
10
|
+
|
|
11
|
+
logger = setup_logger()
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class CsvDataSource(DataSourceBase):
|
|
15
|
+
"""Fonte de dados via CSV."""
|
|
16
|
+
|
|
17
|
+
def get_data(self, symbol, period, count=100):
|
|
18
|
+
"""Retorna dados CSV em uma lista de lista."""
|
|
19
|
+
file_path = os.path.join(conf._INITIAL_CSV_PATH, f"{symbol}{period}.csv")
|
|
20
|
+
logger.info(f"Iniciando coleta de dados via CSV: {file_path}.")
|
|
21
|
+
csv_data = []
|
|
22
|
+
try:
|
|
23
|
+
with open(file_path, encoding="utf-16", newline="") as f:
|
|
24
|
+
lines = csv.reader(f, delimiter=",", quotechar="'")
|
|
25
|
+
for line in lines:
|
|
26
|
+
csv_data.append(line)
|
|
27
|
+
except:
|
|
28
|
+
logger.warning(f"Arquivo {file_path} não encontrado.")
|
|
29
|
+
print("Arquivo %s nao encontrado! Tente novamente" % file_path)
|
|
30
|
+
logger.info("Coleta de dados via CSV finalizada.")
|
|
31
|
+
return csv_data
|