tse-tick 0.3.0__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.
Files changed (38) hide show
  1. tse_tick-0.3.0/LICENSE +21 -0
  2. tse_tick-0.3.0/PKG-INFO +450 -0
  3. tse_tick-0.3.0/README.md +397 -0
  4. tse_tick-0.3.0/pyproject.toml +178 -0
  5. tse_tick-0.3.0/setup.cfg +4 -0
  6. tse_tick-0.3.0/tests/test_api_additions.py +101 -0
  7. tse_tick-0.3.0/tests/test_cli.py +157 -0
  8. tse_tick-0.3.0/tests/test_core.py +1 -0
  9. tse_tick-0.3.0/tests/test_event_window.py +242 -0
  10. tse_tick-0.3.0/tests/test_features.py +243 -0
  11. tse_tick-0.3.0/tests/test_ingest.py +255 -0
  12. tse_tick-0.3.0/tests/test_paper_examples.py +112 -0
  13. tse_tick-0.3.0/tests/test_parquet.py +148 -0
  14. tse_tick-0.3.0/tests/test_parquet_io.py +169 -0
  15. tse_tick-0.3.0/tests/test_query.py +186 -0
  16. tse_tick-0.3.0/tests/test_read_ticks.py +150 -0
  17. tse_tick-0.3.0/tests/test_real_data.py +480 -0
  18. tse_tick-0.3.0/tests/test_schemas.py +1 -0
  19. tse_tick-0.3.0/tse_tick/__init__.py +174 -0
  20. tse_tick-0.3.0/tse_tick/cli.py +268 -0
  21. tse_tick-0.3.0/tse_tick/constants.py +51 -0
  22. tse_tick-0.3.0/tse_tick/core.py +525 -0
  23. tse_tick-0.3.0/tse_tick/enhanced.py +851 -0
  24. tse_tick-0.3.0/tse_tick/event_window.py +237 -0
  25. tse_tick-0.3.0/tse_tick/features.py +275 -0
  26. tse_tick-0.3.0/tse_tick/ingest.py +477 -0
  27. tse_tick-0.3.0/tse_tick/io/__init__.py +0 -0
  28. tse_tick-0.3.0/tse_tick/io/parquet.py +267 -0
  29. tse_tick-0.3.0/tse_tick/py.typed +1 -0
  30. tse_tick-0.3.0/tse_tick/query.py +259 -0
  31. tse_tick-0.3.0/tse_tick/schemas.py +339 -0
  32. tse_tick-0.3.0/tse_tick/translate.py +164 -0
  33. tse_tick-0.3.0/tse_tick.egg-info/PKG-INFO +450 -0
  34. tse_tick-0.3.0/tse_tick.egg-info/SOURCES.txt +36 -0
  35. tse_tick-0.3.0/tse_tick.egg-info/dependency_links.txt +1 -0
  36. tse_tick-0.3.0/tse_tick.egg-info/entry_points.txt +2 -0
  37. tse_tick-0.3.0/tse_tick.egg-info/requires.txt +27 -0
  38. tse_tick-0.3.0/tse_tick.egg-info/top_level.txt +1 -0
tse_tick-0.3.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025-2026 Kazumi Li, Masataka Hayashi, and Peter Romero
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,450 @@
1
+ Metadata-Version: 2.4
2
+ Name: tse-tick
3
+ Version: 0.3.0
4
+ Summary: High-performance Nikkei NEEDS tick data processing with Polars
5
+ Author: Masataka Hayashi, Peter Romero
6
+ Author-email: Kazumi Li <kaiwenli@keio.jp>
7
+ Maintainer-email: Kazumi Li <kaiwenli@keio.jp>
8
+ License-Expression: MIT
9
+ Project-URL: Homepage, https://github.com/tse-tick/tse_tick
10
+ Project-URL: Repository, https://github.com/tse-tick/tse_tick
11
+ Project-URL: Bug Tracker, https://github.com/tse-tick/tse_tick/issues
12
+ Project-URL: Changelog, https://github.com/tse-tick/tse_tick/blob/main/CHANGELOG.md
13
+ Keywords: finance,nikkei,tick-data,market-data,japan,stock,trading,financial-data,time-series,polars,parquet
14
+ Classifier: Development Status :: 4 - Beta
15
+ Classifier: Intended Audience :: Financial and Insurance Industry
16
+ Classifier: Intended Audience :: Science/Research
17
+ Classifier: Topic :: Office/Business :: Financial
18
+ Classifier: Topic :: Scientific/Engineering
19
+ Classifier: Operating System :: OS Independent
20
+ Classifier: Programming Language :: Python :: 3
21
+ Classifier: Programming Language :: Python :: 3.9
22
+ Classifier: Programming Language :: Python :: 3.10
23
+ Classifier: Programming Language :: Python :: 3.11
24
+ Classifier: Programming Language :: Python :: 3.12
25
+ Classifier: Programming Language :: Python :: 3.13
26
+ Requires-Python: >=3.9
27
+ Description-Content-Type: text/markdown
28
+ License-File: LICENSE
29
+ Requires-Dist: polars>=0.20.0
30
+ Requires-Dist: pyarrow>=12.0.0
31
+ Provides-Extra: query
32
+ Requires-Dist: duckdb>=0.9.0; extra == "query"
33
+ Provides-Extra: test
34
+ Requires-Dist: pandas>=1.5.0; extra == "test"
35
+ Requires-Dist: pytest>=7.0; extra == "test"
36
+ Requires-Dist: pytest-cov>=4.0; extra == "test"
37
+ Provides-Extra: dev
38
+ Requires-Dist: pandas>=1.5.0; extra == "dev"
39
+ Requires-Dist: pytest>=7.0; extra == "dev"
40
+ Requires-Dist: pytest-cov>=4.0; extra == "dev"
41
+ Requires-Dist: black>=22.0; extra == "dev"
42
+ Requires-Dist: flake8>=5.0; extra == "dev"
43
+ Requires-Dist: mypy>=0.991; extra == "dev"
44
+ Requires-Dist: jupyter>=1.0; extra == "dev"
45
+ Requires-Dist: notebook>=6.5; extra == "dev"
46
+ Requires-Dist: ipykernel>=6.20; extra == "dev"
47
+ Provides-Extra: docs
48
+ Requires-Dist: sphinx>=5.0; extra == "docs"
49
+ Requires-Dist: sphinx-rtd-theme>=1.0; extra == "docs"
50
+ Requires-Dist: sphinx-autodoc-typehints>=1.19; extra == "docs"
51
+ Requires-Dist: myst-parser>=0.18; extra == "docs"
52
+ Dynamic: license-file
53
+
54
+ # tse_tick
55
+
56
+ A Python library for parsing, filtering, and querying Nikkei NEEDS tick data from the Tokyo Stock Exchange.
57
+
58
+ **Who it's for:** Researchers working with NEEDS tick data who need to convert thousands of zipped CSVs into queryable Parquet stores, filter by ticker or event windows, and handle format changes across historical eras.
59
+
60
+ **What it solves:** NEEDS data is delivered as daily ZIP files (1–27 parts per day) with era-dependent schemas — 2016 used fixed-width records for indices, 2017+ switched to CSV, and individual stocks have 95 columns with complex quote-book nesting. This library detects the format automatically, validates for security, parses everything into clean DataFrames, and writes Hive-partitioned Parquet.
61
+
62
+ **Data access required:** This tool does NOT provide NEEDS data itself. You must have an institutional subscription (Nikkei NEEDS) and access to the raw TICST120/TICSS110/TICIT110/TICIS110 ZIP files. If your data is shared via Google Drive, see [the rclone download guide](https://github.com/tse-tick/tse_tick/blob/main/rclone_guide.md) for mirroring it to local disk.
63
+
64
+ ---
65
+
66
+ ## Features
67
+
68
+ - **4 data types** — TICST120 (individual stock ticks, 95 cols), TICSS110 (daily stock summary, 82 cols), TICIT110 (index ticks, 10 cols), TICIS110 (daily index summary, 17 cols)
69
+ - **Multi-era format support** — 2016 fixed-width (TICIT010/TICIS010) and 2017-2025 CSV, auto-detected from the ZIP filename
70
+ - **Polars backend** — fast CSV parsing, vectorized cleaning, memory-efficient
71
+ - **CLI batch ingestion** — `tse-tick ingest` converts entire years/months/date ranges to partitioned Parquet
72
+ - **Ticker filtering** (`--tickers`) — keep only specific stock codes at read time
73
+ - **Event-window extraction** (`--filter-csv`) — extract ±N minute windows around corporate events with automatic after-hours reaction-anchor shifting
74
+ - **Bilingual columns** — English and Japanese column names via `--language en|jp`
75
+ - **Security guards** — ZIP bomb detection (5 GB max decompressed, 100:1 compression ratio cap, max 5 entries), path traversal prevention, query row limits (10M)
76
+
77
+ ---
78
+
79
+ ## Installation
80
+
81
+ ```bash
82
+ pip install tse-tick # from PyPI: core (polars, pyarrow)
83
+ pip install "tse-tick[query]" # + DuckDB-powered Parquet queries
84
+ ```
85
+
86
+ To work from the latest (unreleased) source instead, install in editable mode:
87
+
88
+ ```bash
89
+ git clone https://github.com/tse-tick/tse_tick.git
90
+ cd tse_tick
91
+
92
+ pip install -e . # core: polars, pyarrow
93
+ pip install -e ".[query]" # + DuckDB-powered Parquet queries
94
+ pip install -e ".[dev]" # + everything for development (tests, linters, jupyter)
95
+ ```
96
+
97
+ Requires Python ≥3.9. Core dependencies are polars and pyarrow; the `query` extra adds DuckDB (see `pyproject.toml`).
98
+
99
+ ---
100
+
101
+ ## Quick Start
102
+
103
+ ### Python API — load a single ZIP
104
+
105
+ ```python
106
+ import tse_tick
107
+
108
+ # Load individual stock tick data (auto-detects data type and year)
109
+ df = tse_tick.create_df("path/to/HTICST120.20230104.1.zip", language="en")
110
+
111
+ # Load with Japanese column names
112
+ df_jp = tse_tick.create_df("path/to/HTICST120.20230104.1.zip", language="jp")
113
+
114
+ # Sample first 1000 rows only
115
+ df_sample = tse_tick.create_df("path/to/HTICST120.20230104.1.zip", rows=1000)
116
+
117
+ # Explicit data type and year (skip auto-detection)
118
+ df = tse_tick.create_df(
119
+ "path/to/file.zip",
120
+ auto_detect=False,
121
+ data_type="individual_stock",
122
+ year=2023,
123
+ )
124
+ ```
125
+
126
+ ### CLI — batch ingest to Parquet
127
+
128
+ ```bash
129
+ # Ingest a date range
130
+ tse-tick ingest \
131
+ --data-type individual_stock \
132
+ --period 20240201-20240205 \
133
+ --input-root /path/to/TSE_DATA \
134
+ --output-root /path/to/PARQUET_STORE
135
+
136
+ # Ingest a full year
137
+ tse-tick ingest \
138
+ --data-type individual_stock \
139
+ --period 2024 \
140
+ --input-root /path/to/TSE_DATA \
141
+ --output-root /path/to/PARQUET_STORE
142
+
143
+ # Ticker-filtered ingest (keep only specified stocks)
144
+ tse-tick ingest \
145
+ --data-type individual_stock \
146
+ --period 2024 \
147
+ --input-root /path/to/TSE_DATA \
148
+ --output-root /path/to/PARQUET_STORE \
149
+ --tickers 7203,6758,9984
150
+
151
+ # Ticker filter from file (one ticker per line)
152
+ tse-tick ingest \
153
+ --data-type individual_stock \
154
+ --period 2024 \
155
+ --input-root /path/to/TSE_DATA \
156
+ --output-root /path/to/PARQUET_STORE \
157
+ --tickers @ticker_list.txt
158
+
159
+ # Event-window filtered ingest (±120 min around each event)
160
+ tse-tick ingest \
161
+ --data-type individual_stock \
162
+ --period 20250106-20250131 \
163
+ --input-root /path/to/TSE_DATA \
164
+ --output-root /path/to/PARQUET_STORE \
165
+ --filter-csv event_filter_list.csv \
166
+ --window 120
167
+ ```
168
+
169
+ ### Query the Parquet store
170
+
171
+ ```python
172
+ import tse_tick
173
+
174
+ # Query specific ticker and date
175
+ df = tse_tick.query_ticks(
176
+ "/path/to/PARQUET_STORE",
177
+ data_type="individual_stock",
178
+ ticker=7203,
179
+ date="20240201",
180
+ start_time="09:00:00",
181
+ end_time="11:30:00",
182
+ )
183
+
184
+ # Get available dates and tickers
185
+ dates = tse_tick.get_available_dates("/path/to/PARQUET_STORE")
186
+ tickers = tse_tick.get_available_tickers("/path/to/PARQUET_STORE", date="20240201")
187
+ ```
188
+
189
+ ### Feature extraction
190
+
191
+ ```python
192
+ import tse_tick
193
+
194
+ df = tse_tick.query_ticks("/store", ticker=7203, date="20220201")
195
+
196
+ # Bid-ask spread
197
+ spread = tse_tick.compute_spread(df)
198
+
199
+ # Order-book depth (10 levels per side)
200
+ depth = tse_tick.compute_depth(df, levels=5, side="both")
201
+
202
+ # Order flow imbalance over rolling window
203
+ ofi = tse_tick.compute_flow_imbalance(df, window="5min")
204
+
205
+ # All features in one pass
206
+ features = tse_tick.compute_all_features(df)
207
+ ```
208
+
209
+ ### Two access patterns
210
+
211
+ `tse_tick` gives you a filtered DataFrame two ways:
212
+
213
+ 1. **Two-stage (scale / repeated work)** — `ingest` the raw ZIPs into a Hive-partitioned Parquet store once, then `query_ticks` it repeatedly. Querying the store prunes by date/ticker and is far faster than re-reading raw files (~694× vs a pandas CSV scan; see [Performance](#performance)).
214
+ 2. **One-shot (quick, targeted exploration)** *(planned for 0.3.0)* — `read_ticks(...)` reads straight from raw ZIPs to a ticker/time-filtered DataFrame with no store to build first; best for a few tickers over a bounded window. Today, `create_df(zip, ticker_filter=...)` already covers the single-file, ticker-filtered case.
215
+
216
+ ---
217
+
218
+ ## Data Types
219
+
220
+ | Code | Internal Name | Output Fields | Description |
221
+ |------|--------------|---------------|-------------|
222
+ | TICST120 | `individual_stock` | 95 | Tick-level executions, 10-level bid/ask quotes, volume |
223
+ | TICSS110 | `stock_summary` | 82 (83 raw) | Daily OHLC, VWAP, session splits, quote statistics |
224
+ | TICIT110 | `indices` | 10 (23 raw, 15 in 2016) | Index tick updates (Nikkei 225, TOPIX, etc.) |
225
+ | TICIS110 | `indices_summary` | 17 (83 raw) | Daily index summary prices |
226
+
227
+ ---
228
+
229
+ ## Multi-Era Format Support
230
+
231
+ The format changed only once, after 2016, and only for the index types (fixed-width to CSV); individual stock and stock summary files were CSV throughout. The library detects the era automatically from the ZIP filename (the year) and applies the correct parser.
232
+
233
+ | Era | Individual Stocks | Stock Summary | Index Ticks | Index Summary |
234
+ |-----|-------------------|---------------|-------------|---------------|
235
+ | **2016** | CSV, 95 cols | CSV, 83 cols | **Fixed-width (69 bytes)** | **Fixed-width (hybrid)** |
236
+ | **2017-2025** | CSV, 95 cols | CSV, 83 cols | CSV, 23 cols | CSV, 83 cols |
237
+
238
+ No user action needed — if your ZIP filename contains `2016`, the fixed-width parser is used automatically for index data.
239
+
240
+ ---
241
+
242
+ ## Performance
243
+
244
+ `tse_tick` is built on Polars (CSV parsing, vectorized cleaning) and DuckDB over Hive-partitioned Parquet (queries). Measured on one day of HTICST120 (4.78 M rows, 95 columns, 2.16 GB raw CSV) on an Intel Core i5-14400F (10-core / 16-thread) with 32 GB RAM, Python 3.11, Polars 1.40, pandas 2.2.
245
+
246
+ | Comparison | Speedup | Source |
247
+ |------------|---------|--------|
248
+ | Polars (16T) vs pandas (Python engine) | **55.5×** | `benchmarks/results_engine_summary.csv` |
249
+ | Polars (16T) vs pandas (C engine, fair baseline) | **22.8×** | `benchmarks/results_engine_summary.csv` |
250
+ | Polars (1 thread) vs pandas (C engine) | **6.2×** | `benchmarks/results_engine_summary.csv` |
251
+ | DuckDB + Hive Parquet vs pandas CSV scan (single-ticker hour slice) | **694.1×** | `benchmarks/results_query.csv` |
252
+ | Parquet (Snappy) storage size vs raw CSV | **22× smaller** (100 MB vs 2.2 GB) | `benchmarks/results_format.csv` |
253
+
254
+ The three Polars speedup numbers are deliberately reported together: against the original pandas Python-engine prototype, against a fair C-engine baseline (all-string dtypes, forced column count), and at single-thread parity to isolate the contribution of threading from the engine itself. Polars wins on all three.
255
+
256
+ `tse_tick` defaults to Polars because the ingest workload (multi-GB daily CSVs, mostly columnar transformations) hits exactly the case where lazy expression planning and parallel CSV parsing dominate; pandas-on-DataFrame's row-oriented model leaves throughput on the table even with the C engine. For querying, the Parquet store + DuckDB combination converts repeated single-ticker / single-date filters from full file scans into partition pruning, which is the source of the ~700× query speedup.
257
+
258
+ To reproduce: `python benchmarks/run_all.py` (see `benchmarks/ENVIRONMENT.md`).
259
+
260
+ ---
261
+
262
+ ## Expected Input Layout
263
+
264
+ The CLI expects NEEDS data organized as delivered by Nikkei:
265
+
266
+ ```
267
+ {input_root}/
268
+ 2016/
269
+ 201601/
270
+ HTICST120.20160104.1.zip
271
+ HTICST120.20160104.2.zip
272
+ ...
273
+ 201602/
274
+ ...
275
+ 2017/
276
+ 201701/
277
+ ...
278
+ ```
279
+
280
+ ---
281
+
282
+ ## Parquet Output Layout
283
+
284
+ Standard ingest produces Hive-partitioned Parquet per ticker per date:
285
+
286
+ ```
287
+ {output_root}/
288
+ individual_stock/
289
+ date=20230104/
290
+ ticker=7203.parquet
291
+ ticker=6758.parquet
292
+ ...
293
+ ```
294
+
295
+ Event-window filtered ingest writes per-date files:
296
+
297
+ ```
298
+ {output_root}/
299
+ year=2025/
300
+ month=01/
301
+ 20250106.parquet
302
+ 20250107.parquet
303
+ ...
304
+ ```
305
+
306
+ ---
307
+
308
+ ## CLI Reference
309
+
310
+ | Flag | Description |
311
+ |------|-------------|
312
+ | `--data-type` (required) | `individual_stock`, `stock_summary`, `indices`, or `indices_summary` |
313
+ | `--input-root` (required) | Root directory with NEEDS ZIPs in `{year}/{yearmonth}/` layout |
314
+ | `--output-root` (required) | Root directory for Parquet output |
315
+ | `--period` | Date range: `YYYY`, `YYYYMM-YYYYMM`, or `YYYYMMDD-YYYYMMDD` |
316
+ | `--language` | Column name language: `en` (default) or `jp` |
317
+ | `--parallel` | Number of parallel workers (default 1, max 8) |
318
+ | `--no-resume` | Disable resume (reprocess dates even if output exists) |
319
+ | `--tickers` | Comma-separated codes or `@file.txt` with one per line. Keeps only these stocks. |
320
+ | `--filter-csv` | Path to event filter CSV. Enables event-window mode. Overrides `--tickers`. |
321
+ | `--window` | Window minutes around each event's reaction anchor (default 120). Only with `--filter-csv`. |
322
+ | `--flat` | Treat input-root as a flat directory (no year/month subdirectories) |
323
+ | `--years` / `--year` | Legacy flags for specifying year(s) directly |
324
+
325
+ ### Event Filter CSV Format
326
+
327
+ When using `--filter-csv`, the file must have these columns:
328
+
329
+ | Column | Description |
330
+ |--------|-------------|
331
+ | `ticker` | 4-digit stock code (string) |
332
+ | `event_date` | Original event date `YYYY-MM-DD` |
333
+ | `event_time` | Original event time `HH:MM` (JST) |
334
+ | `event_type` | Category (`earnings`, `buyback`, `dividend`, etc.) |
335
+ | `session_type` | `intraday` or `after_hours` |
336
+ | `reaction_anchor_dt` | Datetime to center the window on `YYYY-MM-DD HH:MM` (JST) |
337
+ | `zip_date` | TICST120 date `YYYYMMDD` whose ZIP contains the relevant ticks |
338
+
339
+ For after-hours events, `reaction_anchor_dt` shifts to the next trading day's 09:00 open, and `zip_date` points to that next day's ZIP file. This is critical: centering on the event time (e.g., 15:30) would produce empty windows because the market is closed.
340
+
341
+ ---
342
+
343
+ ## Python API Reference
344
+
345
+ ### `create_df(folder_path, language="en", rows=None, auto_detect=True, data_type=None, year=None, ticker_filter=None)`
346
+
347
+ Load and clean tick data from a ZIP file or directory of ZIP files.
348
+
349
+ - `folder_path` — path to a `.zip` file or directory of `.zip` files
350
+ - `language` — `"en"` or `"jp"` for column names
351
+ - `rows` — max rows to return
352
+ - `auto_detect` — if `True`, detect data type and year from path. If `False`, must provide `data_type` and `year`
353
+ - `data_type` — `"individual_stock"`, `"stock_summary"`, `"indices"`, or `"indices_summary"`
354
+ - `year` — data year (e.g., 2023)
355
+ - `ticker_filter` — optional `set` of 4-digit stock codes to pre-filter at line level
356
+
357
+ Returns a Polars DataFrame with English or Japanese column names.
358
+
359
+ ### `export_to_csv(folder_path, output_path=None, language="en", rows=None)`
360
+
361
+ Load and export to CSV. If `output_path` is `None`, generates a filename.
362
+
363
+ ---
364
+
365
+ ## Security
366
+
367
+ Built-in protections for local data processing:
368
+
369
+ | Guard | Value |
370
+ |-------|-------|
371
+ | ZIP bomb detection (max decompressed) | 5 GB |
372
+ | ZIP compression ratio cap | 100:1 |
373
+ | Max ZIP entries | 5 |
374
+ | Max parallel workers | 8 |
375
+ | Query row limit | 10,000,000 |
376
+ | Path traversal prevention | Resolved path validation |
377
+ | SQL injection prevention | Identifier/date/time format validation |
378
+
379
+ ---
380
+
381
+ ## Roadmap (0.3.0)
382
+
383
+ The public API names are **stable** — no renames (an earlier proposal to rename functions to
384
+ yfinance/Polygon/ccxt conventions was reversed). Planned additions are purely additive:
385
+
386
+ - **`read_ticks` one-shot reader** — raw ZIPs → ticker/time-filtered DataFrame without building a Parquet store (see [Two access patterns](#two-access-patterns)).
387
+ - **`translate()` name mapping** — a static lookup from yfinance / Polygon / ccxt names to `tse_tick`'s, so users of those libraries can find the equivalent call without us coupling to their (changing) APIs.
388
+ - **`DataType` / `Language` enums** — for autocomplete and to avoid magic strings.
389
+
390
+ See `PYPI_RELEASE_PLAN.md` for the full plan.
391
+
392
+ ---
393
+
394
+ ## Contributing
395
+
396
+ Contributions are welcome. Please open an issue or submit a pull request.
397
+
398
+ 1. Fork the repository
399
+ 2. Create a feature branch (`git checkout -b feature/your-feature`)
400
+ 3. Commit your changes (`git commit -m 'Add your feature'`)
401
+ 4. Push to the branch (`git push origin feature/your-feature`)
402
+ 5. Open a Pull Request
403
+
404
+ Development setup:
405
+ ```bash
406
+ pip install -e ".[dev]"
407
+ pytest tests/ -v
408
+ ```
409
+
410
+ ---
411
+
412
+ ## Testing
413
+
414
+ ```bash
415
+ pytest tests/ -v
416
+ ```
417
+
418
+ The suite collects **181 tests**. Without a local NEEDS store, **133 pass** and **48 skip**; with a complete NEEDS store, **all 181 pass**. Stage-1
419
+ (ingestion) and Stage-2 (query, order-book features, and
420
+ event-window-from-Parquet) both run with no proprietary data — a session-scoped
421
+ pytest fixture builds a tiny Hive-partitioned Parquet store at test time by
422
+ feeding synthetic, obviously-fake `individual_stock` (TICST120) ZIPs through the
423
+ real ingest pipeline (`tests/synthetic_data.py`, `tests/conftest.py`).
424
+
425
+ The 48 skips load **real NEEDS files** from local paths
426
+ (`test_real_data.py` and the real-ZIP cases in `test_ingest.py`), plus a handful
427
+ of fixtures outside the synthetic store's scope. They run automatically once a
428
+ local NEEDS store is present.
429
+
430
+ ---
431
+
432
+ ## Citation
433
+
434
+ If you use this software in your research, please cite it using the `CITATION.cff` file in the repository. A technical paper describing the library is in preparation.
435
+
436
+ ---
437
+
438
+ ## License
439
+
440
+ [MIT](https://github.com/tse-tick/tse_tick/blob/main/LICENSE)
441
+
442
+ ---
443
+
444
+ ## Authors
445
+
446
+ - **Kazumi Li** — Schema definitions, package architecture, current maintainer
447
+ - **Masataka Hayashi** — Initial pandas-based prototype
448
+ - **Peter Romero** — Original concept and initial project design
449
+
450
+ Developed at Keio University, Nakatsuma Seminar.