mtcli-renko 1.2.0.dev0__py3-none-any.whl → 1.2.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.
@@ -1,354 +1,354 @@
1
- """
2
- RenkoModel profissional.
3
-
4
- Candle mode determinístico
5
- Tick mode híbrido (confirmados + em formação)
6
- Ancoragem correta na abertura da B3
7
- Ajuste UTC da corretora
8
- Margem de segurança na abertura
9
- Reconstrução de caminho do candle (path reconstruction)
10
- Compatível com controller atual
11
- Funciona mesmo com mercado fechado
12
- """
13
-
14
- from dataclasses import dataclass
15
- from typing import List, Optional, NamedTuple
16
- from datetime import datetime, time as dtime, timedelta
17
-
18
- import MetaTrader5 as mt5
19
-
20
- from mtcli.mt5_context import mt5_conexao
21
- from mtcli.logger import setup_logger
22
- from ..marketdata.tick_repository import TickRepository
23
- from ..conf import SESSION_OPEN, SESSION_OPEN_OFFSET_SECONDS, BROKER_UTC_OFFSET
24
-
25
- log = setup_logger(__name__)
26
-
27
-
28
- # ==========================================================
29
- # DATA STRUCTURES
30
- # ==========================================================
31
-
32
- @dataclass
33
- class Brick:
34
- direction: str
35
- open: float
36
- close: float
37
- volume: float = 0
38
- ticks: int = 0
39
-
40
-
41
- class RenkoTickResult(NamedTuple):
42
- confirmados: List[Brick]
43
- em_formacao: Optional[Brick]
44
-
45
-
46
- # ==========================================================
47
- # MODEL
48
- # ==========================================================
49
-
50
- class RenkoModel:
51
-
52
- def __init__(self, symbol: str, brick_size: float):
53
-
54
- self.symbol = symbol
55
- self.brick_size = brick_size
56
- self.repo = TickRepository()
57
-
58
- # ======================================================
59
- # UTIL
60
- # ======================================================
61
-
62
- def _session_start_timestamp(self, data):
63
-
64
- abertura_b3 = datetime.combine(
65
- data,
66
- dtime.fromisoformat(SESSION_OPEN),
67
- )
68
-
69
- abertura_utc = abertura_b3 + timedelta(hours=BROKER_UTC_OFFSET)
70
-
71
- abertura_utc += timedelta(seconds=SESSION_OPEN_OFFSET_SECONDS)
72
-
73
- return int(abertura_utc.timestamp())
74
-
75
- # ======================================================
76
- # RATES (CANDLE MODE)
77
- # ======================================================
78
-
79
- def obter_rates(self, timeframe, quantidade, ancorar_abertura=False):
80
-
81
- with mt5_conexao():
82
-
83
- if not mt5.symbol_select(self.symbol, True):
84
- raise RuntimeError(f"Erro ao selecionar símbolo {self.symbol}")
85
-
86
- if quantidade == 0:
87
- quantidade = 1000
88
-
89
- rates = mt5.copy_rates_from_pos(
90
- self.symbol,
91
- timeframe,
92
- 0,
93
- quantidade,
94
- )
95
-
96
- if rates is None or len(rates) == 0:
97
- return []
98
-
99
- if not ancorar_abertura:
100
- return rates
101
-
102
- ultimo_ts = int(rates[-1]["time"])
103
-
104
- ultimo_dia = datetime.utcfromtimestamp(ultimo_ts).date()
105
-
106
- abertura_ts = self._session_start_timestamp(ultimo_dia)
107
-
108
- filtrados = []
109
-
110
- for r in rates:
111
-
112
- ts = int(r["time"])
113
-
114
- if ts >= abertura_ts:
115
- filtrados.append(r)
116
-
117
- return filtrados
118
-
119
- # ======================================================
120
- # TICKS (BANCO + MT5)
121
- # ======================================================
122
-
123
- def obter_ticks(self, max_ticks=5000, ancorar_abertura=False):
124
-
125
- last_time = self.repo._get_last_tick_time(self.symbol)
126
-
127
- if last_time is None:
128
-
129
- self.repo.sync(self.symbol, days_back=3)
130
- last_time = self.repo._get_last_tick_time(self.symbol)
131
-
132
- else:
133
-
134
- self.repo.sync(self.symbol)
135
-
136
- if last_time is None:
137
- return []
138
-
139
- end_ts = int(datetime.utcnow().timestamp())
140
-
141
- if ancorar_abertura:
142
-
143
- data = datetime.utcfromtimestamp(last_time).date()
144
-
145
- start_ts = self._session_start_timestamp(data)
146
-
147
- else:
148
-
149
- start_ts = 0
150
-
151
- rows = self.repo.get_ticks_between(
152
- self.symbol,
153
- start_ts,
154
- end_ts,
155
- )
156
-
157
- if rows is None or len(rows) == 0:
158
- return []
159
-
160
- return rows[-max_ticks:]
161
-
162
- # ======================================================
163
- # PATH RECONSTRUCTION
164
- # ======================================================
165
-
166
- def _reconstruir_path(self, rate):
167
-
168
- o = float(rate["open"])
169
- h = float(rate["high"])
170
- l = float(rate["low"])
171
- c = float(rate["close"])
172
-
173
- if c >= o:
174
- return [o, l, h, c]
175
-
176
- return [o, h, l, c]
177
-
178
- # ======================================================
179
- # RENKO CANDLE
180
- # ======================================================
181
-
182
- def construir_renko(self, rates, modo="simples") -> List[Brick]:
183
-
184
- if rates is None or len(rates) < 2:
185
- return []
186
-
187
- bricks: List[Brick] = []
188
-
189
- last_price = float(rates[0]["open"])
190
- last_direction: Optional[str] = None
191
-
192
- for rate in rates[1:]:
193
-
194
- path = self._reconstruir_path(rate)
195
-
196
- for price in path:
197
-
198
- # =============================
199
- # movimento de alta
200
- # =============================
201
-
202
- while price - last_price >= self.brick_size:
203
-
204
- # regra reversão clássica
205
- if modo == "classico" and last_direction == "down":
206
-
207
- if price - last_price < self.brick_size * 2:
208
- break
209
-
210
- last_price += self.brick_size
211
-
212
- novo = last_price + self.brick_size
213
-
214
- bricks.append(
215
- Brick("up", last_price, novo)
216
- )
217
-
218
- last_price = novo
219
- last_direction = "up"
220
-
221
- # =============================
222
- # movimento de baixa
223
- # =============================
224
-
225
- while last_price - price >= self.brick_size:
226
-
227
- if modo == "classico" and last_direction == "up":
228
-
229
- if last_price - price < self.brick_size * 2:
230
- break
231
-
232
- last_price -= self.brick_size
233
-
234
- novo = last_price - self.brick_size
235
-
236
- bricks.append(
237
- Brick("down", last_price, novo)
238
- )
239
-
240
- last_price = novo
241
- last_direction = "down"
242
-
243
- return bricks
244
-
245
- # ======================================================
246
- # RENKO TICK MODE
247
- # ======================================================
248
-
249
- def construir_renko_ticks(self, ticks, modo="simples") -> RenkoTickResult:
250
-
251
- if ticks is None or len(ticks) < 2:
252
- return RenkoTickResult([], None)
253
-
254
- bricks: List[Brick] = []
255
-
256
- last_price = float(ticks[0][3])
257
- last_direction: Optional[str] = None
258
- volume_acumulado = 0
259
- ticks_acumulados = 0
260
-
261
- for tick in ticks[1:]:
262
-
263
- price = float(tick[3])
264
- volume = float(tick[4])
265
-
266
- volume_acumulado += volume
267
- ticks_acumulados += 1
268
-
269
- # =============================
270
- # movimento de alta
271
- # =============================
272
-
273
- while price - last_price >= self.brick_size:
274
-
275
- if modo == "classico" and last_direction == "down":
276
-
277
- if price - last_price < self.brick_size * 2:
278
- break
279
-
280
- last_price += self.brick_size
281
-
282
- novo = last_price + self.brick_size
283
-
284
- bricks.append(
285
- Brick(
286
- direction="up",
287
- open=last_price,
288
- close=novo,
289
- volume=volume_acumulado,
290
- ticks=ticks_acumulados,
291
- )
292
- )
293
-
294
- volume_acumulado = 0
295
- ticks_acumulados = 0
296
- last_price = novo
297
- last_direction = "up"
298
-
299
- # =============================
300
- # movimento de baixa
301
- # =============================
302
-
303
- while last_price - price >= self.brick_size:
304
-
305
- if modo == "classico" and last_direction == "up":
306
-
307
- if last_price - price < self.brick_size * 2:
308
- break
309
-
310
- last_price -= self.brick_size
311
-
312
- novo = last_price - self.brick_size
313
-
314
- bricks.append(
315
- Brick(
316
- direction="down",
317
- open=last_price,
318
- close=novo,
319
- volume=volume_acumulado,
320
- ticks=ticks_acumulados,
321
- )
322
- )
323
-
324
- volume_acumulado = 0
325
- ticks_acumulados = 0
326
- last_price = novo
327
- last_direction = "down"
328
-
329
- # =================================
330
- # brick em formação
331
- # =================================
332
-
333
- ultimo_preco = float(ticks[-1][3])
334
-
335
- diferenca = ultimo_preco - last_price
336
-
337
- em_formacao = None
338
-
339
- if abs(diferenca) > 0:
340
-
341
- direcao = "up" if diferenca > 0 else "down"
342
-
343
- em_formacao = Brick(
344
- direction=direcao,
345
- open=last_price,
346
- close=ultimo_preco,
347
- volume=volume_acumulado,
348
- ticks=ticks_acumulados,
349
- )
350
-
351
- return RenkoTickResult(
352
- confirmados=bricks,
353
- em_formacao=em_formacao,
354
- )
1
+ """
2
+ RenkoModel profissional.
3
+
4
+ Candle mode determinístico
5
+ Tick mode híbrido (confirmados + em formação)
6
+ Ancoragem correta na abertura da B3
7
+ Ajuste UTC da corretora
8
+ Margem de segurança na abertura
9
+ Reconstrução de caminho do candle (path reconstruction)
10
+ Compatível com controller atual
11
+ Funciona mesmo com mercado fechado
12
+ """
13
+
14
+ from dataclasses import dataclass
15
+ from typing import List, Optional, NamedTuple
16
+ from datetime import datetime, time as dtime, timedelta
17
+
18
+ import MetaTrader5 as mt5
19
+
20
+ from mtcli.mt5_context import mt5_conexao
21
+ from mtcli.logger import setup_logger
22
+ from ..marketdata.tick_repository import TickRepository
23
+ from ..conf import SESSION_OPEN, SESSION_OPEN_OFFSET_SECONDS, BROKER_UTC_OFFSET
24
+
25
+ log = setup_logger(__name__)
26
+
27
+
28
+ # ==========================================================
29
+ # DATA STRUCTURES
30
+ # ==========================================================
31
+
32
+ @dataclass
33
+ class Brick:
34
+ direction: str
35
+ open: float
36
+ close: float
37
+ volume: float = 0
38
+ ticks: int = 0
39
+
40
+
41
+ class RenkoTickResult(NamedTuple):
42
+ confirmados: List[Brick]
43
+ em_formacao: Optional[Brick]
44
+
45
+
46
+ # ==========================================================
47
+ # MODEL
48
+ # ==========================================================
49
+
50
+ class RenkoModel:
51
+
52
+ def __init__(self, symbol: str, brick_size: float):
53
+
54
+ self.symbol = symbol
55
+ self.brick_size = brick_size
56
+ self.repo = TickRepository()
57
+
58
+ # ======================================================
59
+ # UTIL
60
+ # ======================================================
61
+
62
+ def _session_start_timestamp(self, data):
63
+
64
+ abertura_b3 = datetime.combine(
65
+ data,
66
+ dtime.fromisoformat(SESSION_OPEN),
67
+ )
68
+
69
+ abertura_utc = abertura_b3 + timedelta(hours=BROKER_UTC_OFFSET)
70
+
71
+ abertura_utc += timedelta(seconds=SESSION_OPEN_OFFSET_SECONDS)
72
+
73
+ return int(abertura_utc.timestamp())
74
+
75
+ # ======================================================
76
+ # RATES (CANDLE MODE)
77
+ # ======================================================
78
+
79
+ def obter_rates(self, timeframe, quantidade, ancorar_abertura=False):
80
+
81
+ with mt5_conexao():
82
+
83
+ if not mt5.symbol_select(self.symbol, True):
84
+ raise RuntimeError(f"Erro ao selecionar símbolo {self.symbol}")
85
+
86
+ if quantidade == 0:
87
+ quantidade = 1000
88
+
89
+ rates = mt5.copy_rates_from_pos(
90
+ self.symbol,
91
+ timeframe,
92
+ 0,
93
+ quantidade,
94
+ )
95
+
96
+ if rates is None or len(rates) == 0:
97
+ return []
98
+
99
+ if not ancorar_abertura:
100
+ return rates
101
+
102
+ ultimo_ts = int(rates[-1]["time"])
103
+
104
+ ultimo_dia = datetime.utcfromtimestamp(ultimo_ts).date()
105
+
106
+ abertura_ts = self._session_start_timestamp(ultimo_dia)
107
+
108
+ filtrados = []
109
+
110
+ for r in rates:
111
+
112
+ ts = int(r["time"])
113
+
114
+ if ts >= abertura_ts:
115
+ filtrados.append(r)
116
+
117
+ return filtrados
118
+
119
+ # ======================================================
120
+ # TICKS (BANCO + MT5)
121
+ # ======================================================
122
+
123
+ def obter_ticks(self, max_ticks=5000, ancorar_abertura=False):
124
+
125
+ last_time = self.repo._get_last_tick_time(self.symbol)
126
+
127
+ if last_time is None:
128
+
129
+ self.repo.sync(self.symbol, days_back=3)
130
+ last_time = self.repo._get_last_tick_time(self.symbol)
131
+
132
+ else:
133
+
134
+ self.repo.sync(self.symbol)
135
+
136
+ if last_time is None:
137
+ return []
138
+
139
+ end_ts = int(datetime.utcnow().timestamp())
140
+
141
+ if ancorar_abertura:
142
+
143
+ data = datetime.utcfromtimestamp(last_time).date()
144
+
145
+ start_ts = self._session_start_timestamp(data)
146
+
147
+ else:
148
+
149
+ start_ts = 0
150
+
151
+ rows = self.repo.get_ticks_between(
152
+ self.symbol,
153
+ start_ts,
154
+ end_ts,
155
+ )
156
+
157
+ if rows is None or len(rows) == 0:
158
+ return []
159
+
160
+ return rows[-max_ticks:]
161
+
162
+ # ======================================================
163
+ # PATH RECONSTRUCTION
164
+ # ======================================================
165
+
166
+ def _reconstruir_path(self, rate):
167
+
168
+ o = float(rate["open"])
169
+ h = float(rate["high"])
170
+ l = float(rate["low"])
171
+ c = float(rate["close"])
172
+
173
+ if c >= o:
174
+ return [o, l, h, c]
175
+
176
+ return [o, h, l, c]
177
+
178
+ # ======================================================
179
+ # RENKO CANDLE
180
+ # ======================================================
181
+
182
+ def construir_renko(self, rates, modo="simples") -> List[Brick]:
183
+
184
+ if rates is None or len(rates) < 2:
185
+ return []
186
+
187
+ bricks: List[Brick] = []
188
+
189
+ last_price = float(rates[0]["open"])
190
+ last_direction: Optional[str] = None
191
+
192
+ for rate in rates[1:]:
193
+
194
+ path = self._reconstruir_path(rate)
195
+
196
+ for price in path:
197
+
198
+ # =============================
199
+ # movimento de alta
200
+ # =============================
201
+
202
+ while price - last_price >= self.brick_size:
203
+
204
+ # regra reversão clássica
205
+ if modo == "classico" and last_direction == "down":
206
+
207
+ if price - last_price < self.brick_size * 2:
208
+ break
209
+
210
+ last_price += self.brick_size
211
+
212
+ novo = last_price + self.brick_size
213
+
214
+ bricks.append(
215
+ Brick("up", last_price, novo)
216
+ )
217
+
218
+ last_price = novo
219
+ last_direction = "up"
220
+
221
+ # =============================
222
+ # movimento de baixa
223
+ # =============================
224
+
225
+ while last_price - price >= self.brick_size:
226
+
227
+ if modo == "classico" and last_direction == "up":
228
+
229
+ if last_price - price < self.brick_size * 2:
230
+ break
231
+
232
+ last_price -= self.brick_size
233
+
234
+ novo = last_price - self.brick_size
235
+
236
+ bricks.append(
237
+ Brick("down", last_price, novo)
238
+ )
239
+
240
+ last_price = novo
241
+ last_direction = "down"
242
+
243
+ return bricks
244
+
245
+ # ======================================================
246
+ # RENKO TICK MODE
247
+ # ======================================================
248
+
249
+ def construir_renko_ticks(self, ticks, modo="simples") -> RenkoTickResult:
250
+
251
+ if ticks is None or len(ticks) < 2:
252
+ return RenkoTickResult([], None)
253
+
254
+ bricks: List[Brick] = []
255
+
256
+ last_price = float(ticks[0][3])
257
+ last_direction: Optional[str] = None
258
+ volume_acumulado = 0
259
+ ticks_acumulados = 0
260
+
261
+ for tick in ticks[1:]:
262
+
263
+ price = float(tick[3])
264
+ volume = float(tick[4])
265
+
266
+ volume_acumulado += volume
267
+ ticks_acumulados += 1
268
+
269
+ # =============================
270
+ # movimento de alta
271
+ # =============================
272
+
273
+ while price - last_price >= self.brick_size:
274
+
275
+ if modo == "classico" and last_direction == "down":
276
+
277
+ if price - last_price < self.brick_size * 2:
278
+ break
279
+
280
+ last_price += self.brick_size
281
+
282
+ novo = last_price + self.brick_size
283
+
284
+ bricks.append(
285
+ Brick(
286
+ direction="up",
287
+ open=last_price,
288
+ close=novo,
289
+ volume=volume_acumulado,
290
+ ticks=ticks_acumulados,
291
+ )
292
+ )
293
+
294
+ volume_acumulado = 0
295
+ ticks_acumulados = 0
296
+ last_price = novo
297
+ last_direction = "up"
298
+
299
+ # =============================
300
+ # movimento de baixa
301
+ # =============================
302
+
303
+ while last_price - price >= self.brick_size:
304
+
305
+ if modo == "classico" and last_direction == "up":
306
+
307
+ if last_price - price < self.brick_size * 2:
308
+ break
309
+
310
+ last_price -= self.brick_size
311
+
312
+ novo = last_price - self.brick_size
313
+
314
+ bricks.append(
315
+ Brick(
316
+ direction="down",
317
+ open=last_price,
318
+ close=novo,
319
+ volume=volume_acumulado,
320
+ ticks=ticks_acumulados,
321
+ )
322
+ )
323
+
324
+ volume_acumulado = 0
325
+ ticks_acumulados = 0
326
+ last_price = novo
327
+ last_direction = "down"
328
+
329
+ # =================================
330
+ # brick em formação
331
+ # =================================
332
+
333
+ ultimo_preco = float(ticks[-1][3])
334
+
335
+ diferenca = ultimo_preco - last_price
336
+
337
+ em_formacao = None
338
+
339
+ if abs(diferenca) > 0:
340
+
341
+ direcao = "up" if diferenca > 0 else "down"
342
+
343
+ em_formacao = Brick(
344
+ direction=direcao,
345
+ open=last_price,
346
+ close=ultimo_preco,
347
+ volume=volume_acumulado,
348
+ ticks=ticks_acumulados,
349
+ )
350
+
351
+ return RenkoTickResult(
352
+ confirmados=bricks,
353
+ em_formacao=em_formacao,
354
+ )
@@ -156,7 +156,7 @@ def exibir_renko(resultado, numerar=False):
156
156
  # BLOCOS CONFIRMADOS
157
157
  # ------------------------------------------------------
158
158
 
159
- click.echo("Direcao Volume Abertura Fechamento")
159
+ click.echo("Direcao Abertura Fechamento Volume")
160
160
 
161
161
  for i, brick in enumerate(bricks, start=1):
162
162
 
@@ -168,16 +168,16 @@ def exibir_renko(resultado, numerar=False):
168
168
  if numerar:
169
169
  linha = (
170
170
  f"{i} {simbolo} "
171
- f"{brick.volume:.0f} "
172
171
  f"{brick.open:.{DIGITS}f} "
173
- f"{brick.close:.{DIGITS}f}"
172
+ f"{brick.close:.{DIGITS}f} "
173
+ f"{brick.volume:.0f}"
174
174
  )
175
175
  else:
176
176
  linha = (
177
177
  f"{simbolo} "
178
- f"{brick.volume:.0f} "
179
178
  f"{brick.open:.{DIGITS}f} "
180
- f"{brick.close:.{DIGITS}f}"
179
+ f"{brick.close:.{DIGITS}f} "
180
+ f"{brick.volume:.0f}"
181
181
  )
182
182
 
183
183
  click.echo(linha)
@@ -197,9 +197,9 @@ def exibir_renko(resultado, numerar=False):
197
197
 
198
198
  linha = (
199
199
  f"FORMANDO {simbolo} "
200
- f"{em_formacao.volume:.0f} "
201
200
  f"{em_formacao.open:.{DIGITS}f} "
202
- f"{em_formacao.close:.{DIGITS}f}"
201
+ f"{em_formacao.close:.{DIGITS}f} "
202
+ f"{em_formacao.volume:.0f}"
203
203
  )
204
204
 
205
205
  click.echo(linha)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mtcli-renko
3
- Version: 1.2.0.dev0
3
+ Version: 1.2.0.dev1
4
4
  Summary: Renko plugin institucional para mtcli (MetaTrader 5)
5
5
  License-Expression: MIT
6
6
  License-File: LICENSE
@@ -9,14 +9,14 @@ mtcli_renko/marketdata/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3
9
9
  mtcli_renko/marketdata/tick_cache.py,sha256=s-ZfmHBpX1la7WzUF-pRoEUK0H5i3MsPjEtgsBLSSUo,434
10
10
  mtcli_renko/marketdata/tick_repository.py,sha256=39LZK4CQuGSudQdCO57-HNqptut2qp-qB1kaVWx0C0E,3832
11
11
  mtcli_renko/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
- mtcli_renko/models/renko_model.py,sha256=sOD4B-nPZqnY8p0QDxikJrN6kq_mtEjCgRw0-5LXCbg,9875
12
+ mtcli_renko/models/renko_model.py,sha256=wu9cmegSFV7Vq4LeYOeEgY3L8ixi9EXBKUTIU6FyV9U,9521
13
13
  mtcli_renko/plugin.py,sha256=uAnXwzvdqG4UFm1T2hkYx2n72Uj3EScLtWwUezS_BEQ,1388
14
14
  mtcli_renko/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
15
  mtcli_renko/utils/renko_stats.py,sha256=TWqu6tLVZRdWw4EWqJHhaMXvq_vPyqULlGk2qHJ1HRM,2023
16
16
  mtcli_renko/views/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
- mtcli_renko/views/renko_view.py,sha256=vajKK2_RHwbCGjn134ZZDBxtqeC_0zpuAnhl3OiZwEA,5096
18
- mtcli_renko-1.2.0.dev0.dist-info/entry_points.txt,sha256=vx7prPn2X6-W_eZrypCeQIROD1OesHHuYDROwDkPEKU,57
19
- mtcli_renko-1.2.0.dev0.dist-info/licenses/LICENSE,sha256=cTMDdXnDTPMMBwolOaoLoDpxa1esGLBZ28hmtiFCu1g,1092
20
- mtcli_renko-1.2.0.dev0.dist-info/METADATA,sha256=yrme8HWh4_4r_5MiNf3m2f4aXic9MFBG6PQUZmPrq84,6931
21
- mtcli_renko-1.2.0.dev0.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
22
- mtcli_renko-1.2.0.dev0.dist-info/RECORD,,
17
+ mtcli_renko/views/renko_view.py,sha256=G7czZbmxdLqgdKBxtXnWJumWmoJRjW4689E_N-JOgk4,5096
18
+ mtcli_renko-1.2.0.dev1.dist-info/entry_points.txt,sha256=vx7prPn2X6-W_eZrypCeQIROD1OesHHuYDROwDkPEKU,57
19
+ mtcli_renko-1.2.0.dev1.dist-info/licenses/LICENSE,sha256=cTMDdXnDTPMMBwolOaoLoDpxa1esGLBZ28hmtiFCu1g,1092
20
+ mtcli_renko-1.2.0.dev1.dist-info/METADATA,sha256=bazrzPT2ApHzujz26xlm9esflaWlB9H7UtSZMr5l39E,6931
21
+ mtcli_renko-1.2.0.dev1.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
22
+ mtcli_renko-1.2.0.dev1.dist-info/RECORD,,