exness-data-preprocess 0.1.0__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.
@@ -0,0 +1,506 @@
1
+ Metadata-Version: 2.4
2
+ Name: exness-data-preprocess
3
+ Version: 0.1.0
4
+ Summary: Professional Exness forex tick data preprocessing with optimal compression (Parquet Zstd-22) and DuckDB OHLC generation. Provides efficient storage (9% smaller than ZIP) with lossless precision and direct queryability.
5
+ Project-URL: Homepage, https://github.com/terrylica/exness-data-preprocess
6
+ Project-URL: Documentation, https://github.com/terrylica/exness-data-preprocess#readme
7
+ Project-URL: Repository, https://github.com/terrylica/exness-data-preprocess.git
8
+ Project-URL: Bug Tracker, https://github.com/terrylica/exness-data-preprocess/issues
9
+ Project-URL: Source Code, https://github.com/terrylica/exness-data-preprocess
10
+ Project-URL: Changelog, https://github.com/terrylica/exness-data-preprocess/blob/main/CHANGELOG.md
11
+ Author-email: Eon Labs <terry@eonlabs.com>
12
+ Maintainer-email: Terry Li <terry@eonlabs.com>
13
+ License: MIT
14
+ License-File: AUTHORS.md
15
+ License-File: LICENSE
16
+ Keywords: backtesting,compression,data-engineering,duckdb,efficient-storage,eurusd,exness,financial-data,forex,forex-data,lossless,microstructure,ohlc,pandas,parquet,preprocessing,pyarrow,quantitative-finance,queryable,tick-data,time-series,zstd
17
+ Classifier: Development Status :: 3 - Alpha
18
+ Classifier: Intended Audience :: Developers
19
+ Classifier: Intended Audience :: Financial and Insurance Industry
20
+ Classifier: License :: OSI Approved :: MIT License
21
+ Classifier: Operating System :: OS Independent
22
+ Classifier: Programming Language :: Python :: 3
23
+ Classifier: Programming Language :: Python :: 3.9
24
+ Classifier: Programming Language :: Python :: 3.10
25
+ Classifier: Programming Language :: Python :: 3.11
26
+ Classifier: Programming Language :: Python :: 3.12
27
+ Classifier: Programming Language :: Python :: 3.13
28
+ Classifier: Topic :: Office/Business :: Financial :: Investment
29
+ Classifier: Topic :: Scientific/Engineering :: Information Analysis
30
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
31
+ Requires-Python: >=3.9
32
+ Requires-Dist: duckdb>=0.9.0
33
+ Requires-Dist: httpx>=0.25.0
34
+ Requires-Dist: pandas>=2.0.0
35
+ Requires-Dist: pyarrow>=16.0.0
36
+ Requires-Dist: tqdm>=4.65.0
37
+ Provides-Extra: dev
38
+ Requires-Dist: black>=23.0.0; extra == 'dev'
39
+ Requires-Dist: mypy>=1.5.0; extra == 'dev'
40
+ Requires-Dist: pytest-cov>=4.0.0; extra == 'dev'
41
+ Requires-Dist: pytest>=7.0.0; extra == 'dev'
42
+ Requires-Dist: ruff>=0.1.0; extra == 'dev'
43
+ Provides-Extra: test
44
+ Requires-Dist: pytest-cov>=4.0.0; extra == 'test'
45
+ Requires-Dist: pytest>=7.0.0; extra == 'test'
46
+ Description-Content-Type: text/markdown
47
+
48
+ # Exness Data Preprocess v2.0.0
49
+
50
+ [![PyPI version](https://img.shields.io/pypi/v/exness-data-preprocess.svg)](https://pypi.org/project/exness-data-preprocess/)
51
+ [![Python versions](https://img.shields.io/pypi/pyversions/exness-data-preprocess.svg)](https://pypi.org/project/exness-data-preprocess/)
52
+ [![License](https://img.shields.io/pypi/l/exness-data-preprocess.svg)](https://github.com/terrylica/exness-data-preprocess/blob/main/LICENSE)
53
+ [![CI](https://github.com/terrylica/exness-data-preprocess/workflows/CI/badge.svg)](https://github.com/terrylica/exness-data-preprocess/actions)
54
+ [![Downloads](https://img.shields.io/pypi/dm/exness-data-preprocess.svg)](https://pypi.org/project/exness-data-preprocess/)
55
+ [![Code style: ruff](https://img.shields.io/badge/code%20style-ruff-000000.svg)](https://github.com/astral-sh/ruff)
56
+
57
+ Professional forex tick data preprocessing with unified single-file DuckDB storage. Provides incremental updates, dual-variant storage (Raw_Spread + Standard), and Phase7 9-column OHLC schema with sub-15ms query performance.
58
+
59
+ ## Features
60
+
61
+ - **Unified Single-File Architecture**: One DuckDB file per instrument (eurusd.duckdb)
62
+ - **Incremental Updates**: Automatic gap detection and download only missing months
63
+ - **Dual-Variant Storage**: Raw_Spread (primary) + Standard (reference) in same database
64
+ - **Phase7 OHLC Schema**: 9-column bars with dual spreads and dual tick counts
65
+ - **Fast Queries**: Date range queries with sub-15ms performance
66
+ - **On-Demand Resampling**: Any timeframe (5m, 1h, 1d) resampled in <15ms
67
+ - **PRIMARY KEY Constraints**: Prevents duplicate data during incremental updates
68
+ - **Simple API**: Clean Python API for all operations
69
+
70
+ ## Installation
71
+
72
+ ```bash
73
+ # From PyPI (when published)
74
+ pip install exness-data-preprocess
75
+
76
+ # From source
77
+ git clone https://github.com/Eon-Labs/exness-data-preprocess.git
78
+ cd exness-data-preprocess
79
+ pip install -e .
80
+
81
+ # Using uv (recommended)
82
+ uv pip install exness-data-preprocess
83
+ ```
84
+
85
+ ## Quick Start
86
+
87
+ ### Python API
88
+
89
+ ```python
90
+ import exness_data_preprocess as edp
91
+
92
+ # Initialize processor
93
+ processor = edp.ExnessDataProcessor(base_dir="~/eon/exness-data")
94
+
95
+ # Download 3 years of EURUSD data (automatic gap detection)
96
+ result = processor.update_data(
97
+ pair="EURUSD",
98
+ start_date="2022-01-01",
99
+ delete_zip=True,
100
+ )
101
+
102
+ print(f"Months added: {result['months_added']}")
103
+ print(f"Raw ticks: {result['raw_ticks_added']:,}")
104
+ print(f"Standard ticks: {result['standard_ticks_added']:,}")
105
+ print(f"OHLC bars: {result['ohlc_bars']:,}")
106
+ print(f"Database size: {result['duckdb_size_mb']:.2f} MB")
107
+
108
+ # Query 1-minute OHLC bars for January 2024
109
+ df_1m = processor.query_ohlc(
110
+ pair="EURUSD",
111
+ timeframe="1m",
112
+ start_date="2024-01-01",
113
+ end_date="2024-01-31",
114
+ )
115
+ print(df_1m.head())
116
+
117
+ # Query raw tick data for September 2024
118
+ df_ticks = processor.query_ticks(
119
+ pair="EURUSD",
120
+ variant="raw_spread",
121
+ start_date="2024-09-01",
122
+ end_date="2024-09-30",
123
+ )
124
+ print(f"Ticks: {len(df_ticks):,}")
125
+ ```
126
+
127
+ ## Architecture v2.0.0
128
+
129
+ ### Data Flow
130
+
131
+ ```
132
+ Exness Public Repository (monthly ZIPs, both variants)
133
+ ↓
134
+ Automatic Gap Detection
135
+ ↓
136
+ Download Only Missing Months (Raw_Spread + Standard)
137
+ ↓
138
+ DuckDB Single-File Storage (PRIMARY KEY prevents duplicates)
139
+ ↓
140
+ Phase7 9-Column OHLC Generation (dual spreads + dual tick counts)
141
+ ↓
142
+ Query Interface (date ranges, SQL filters, on-demand resampling)
143
+ ```
144
+
145
+ ### Storage Format
146
+
147
+ **Single File Per Instrument**: `~/eon/exness-data/eurusd.duckdb`
148
+
149
+ **Schema**:
150
+ - `raw_spread_ticks` table: Timestamp (PK), Bid, Ask
151
+ - `standard_ticks` table: Timestamp (PK), Bid, Ask
152
+ - `ohlc_1m` table: Phase7 9-column schema
153
+ - `metadata` table: Coverage tracking
154
+
155
+ **Phase7 9-Column OHLC**:
156
+ 1. `Timestamp` - Bar timestamp
157
+ 2. `Open` - Opening price
158
+ 3. `High` - High price
159
+ 4. `Low` - Low price
160
+ 5. `Close` - Closing price
161
+ 6. `raw_spread_avg` - Average spread from Raw_Spread variant
162
+ 7. `standard_spread_avg` - Average spread from Standard variant
163
+ 8. `tick_count_raw_spread` - Tick count from Raw_Spread variant
164
+ 9. `tick_count_standard` - Tick count from Standard variant
165
+
166
+ ### Directory Structure
167
+
168
+ **Default Location**: `~/eon/exness-data/` (outside project workspace)
169
+
170
+ ```
171
+ ~/eon/exness-data/
172
+ ├── eurusd.duckdb # Single file for all EURUSD data
173
+ ├── gbpusd.duckdb # Single file for all GBPUSD data
174
+ ├── xauusd.duckdb # Single file for all XAUUSD data
175
+ └── temp/
176
+ └── (temporary ZIP files)
177
+ ```
178
+
179
+ **Why Single-File Per Instrument?**
180
+ - **Unified Storage**: All years in one database
181
+ - **Incremental Updates**: Automatic gap detection and download only missing months
182
+ - **No Duplicates**: PRIMARY KEY constraints prevent duplicate data
183
+ - **Fast Queries**: Date range queries with sub-15ms performance
184
+ - **Scalability**: Multi-year data in ~2 GB per instrument (3 years)
185
+
186
+ ## Usage Examples
187
+
188
+ ### Example 1: Initial Download and Incremental Updates
189
+
190
+ ```python
191
+ import exness_data_preprocess as edp
192
+
193
+ processor = edp.ExnessDataProcessor()
194
+
195
+ # Initial download (3-year history)
196
+ result = processor.update_data(
197
+ pair="EURUSD",
198
+ start_date="2022-01-01",
199
+ delete_zip=True,
200
+ )
201
+
202
+ # Run again - only downloads new months since last update
203
+ result = processor.update_data(
204
+ pair="EURUSD",
205
+ start_date="2022-01-01",
206
+ )
207
+ print(f"Months added: {result['months_added']} (0 if up to date)")
208
+ ```
209
+
210
+ ### Example 2: Check Data Coverage
211
+
212
+ ```python
213
+ coverage = processor.get_data_coverage("EURUSD")
214
+
215
+ print(f"Database exists: {coverage['database_exists']}")
216
+ print(f"Raw_Spread ticks: {coverage['raw_spread_ticks']:,}")
217
+ print(f"Standard ticks: {coverage['standard_ticks']:,}")
218
+ print(f"OHLC bars: {coverage['ohlc_bars']:,}")
219
+ print(f"Date range: {coverage['earliest_date']} to {coverage['latest_date']}")
220
+ print(f"Days covered: {coverage['date_range_days']}")
221
+ print(f"Database size: {coverage['duckdb_size_mb']:.2f} MB")
222
+ ```
223
+
224
+ ### Example 3: Query OHLC with Date Ranges
225
+
226
+ ```python
227
+ # Query 1-minute bars for January 2024
228
+ df_1m = processor.query_ohlc(
229
+ pair="EURUSD",
230
+ timeframe="1m",
231
+ start_date="2024-01-01",
232
+ end_date="2024-01-31",
233
+ )
234
+
235
+ # Query 1-hour bars for Q1 2024 (resampled on-demand)
236
+ df_1h = processor.query_ohlc(
237
+ pair="EURUSD",
238
+ timeframe="1h",
239
+ start_date="2024-01-01",
240
+ end_date="2024-03-31",
241
+ )
242
+
243
+ # Query daily bars for entire 2024
244
+ df_1d = processor.query_ohlc(
245
+ pair="EURUSD",
246
+ timeframe="1d",
247
+ start_date="2024-01-01",
248
+ end_date="2024-12-31",
249
+ )
250
+
251
+ print(f"1m bars: {len(df_1m):,}")
252
+ print(f"1h bars: {len(df_1h):,}")
253
+ print(f"1d bars: {len(df_1d):,}")
254
+ ```
255
+
256
+ ### Example 4: Query Ticks with Date Ranges
257
+
258
+ ```python
259
+ # Query Raw_Spread ticks for September 2024
260
+ df_raw = processor.query_ticks(
261
+ pair="EURUSD",
262
+ variant="raw_spread",
263
+ start_date="2024-09-01",
264
+ end_date="2024-09-30",
265
+ )
266
+
267
+ print(f"Raw_Spread ticks: {len(df_raw):,}")
268
+ print(f"Columns: {list(df_raw.columns)}")
269
+
270
+ # Calculate spread statistics
271
+ df_raw['Spread'] = df_raw['Ask'] - df_raw['Bid']
272
+ print(f"Mean spread: {df_raw['Spread'].mean() * 10000:.4f} pips")
273
+ print(f"Zero-spreads: {((df_raw['Spread'] == 0).sum() / len(df_raw) * 100):.2f}%")
274
+ ```
275
+
276
+ ### Example 5: Query with SQL Filters
277
+
278
+ ```python
279
+ # Query only zero-spread ticks
280
+ df_zero = processor.query_ticks(
281
+ pair="EURUSD",
282
+ variant="raw_spread",
283
+ start_date="2024-09-01",
284
+ end_date="2024-09-01",
285
+ filter_sql="Bid = Ask",
286
+ )
287
+ print(f"Zero-spread ticks: {len(df_zero):,}")
288
+
289
+ # Query high-price ticks
290
+ df_high = processor.query_ticks(
291
+ pair="EURUSD",
292
+ variant="raw_spread",
293
+ start_date="2024-09-01",
294
+ end_date="2024-09-30",
295
+ filter_sql="Bid > 1.11",
296
+ )
297
+ print(f"High-price ticks: {len(df_high):,}")
298
+ ```
299
+
300
+ ### Example 6: Process Multiple Instruments
301
+
302
+ ```python
303
+ processor = edp.ExnessDataProcessor()
304
+
305
+ # Process multiple pairs
306
+ pairs = ["EURUSD", "GBPUSD", "XAUUSD"]
307
+
308
+ for pair in pairs:
309
+ print(f"Processing {pair}...")
310
+ result = processor.update_data(
311
+ pair=pair,
312
+ start_date="2023-01-01",
313
+ delete_zip=True,
314
+ )
315
+ print(f" Months added: {result['months_added']}")
316
+ print(f" Database size: {result['duckdb_size_mb']:.2f} MB")
317
+ ```
318
+
319
+ ### Example 7: Parallel Processing
320
+
321
+ ```python
322
+ from concurrent.futures import ThreadPoolExecutor, as_completed
323
+
324
+ def process_instrument(pair, start_date):
325
+ processor = edp.ExnessDataProcessor()
326
+ return processor.update_data(pair=pair, start_date=start_date, delete_zip=True)
327
+
328
+ instruments = [
329
+ ("EURUSD", "2023-01-01"),
330
+ ("GBPUSD", "2023-01-01"),
331
+ ("XAUUSD", "2023-01-01"),
332
+ ("USDJPY", "2023-01-01"),
333
+ ]
334
+
335
+ with ThreadPoolExecutor(max_workers=4) as executor:
336
+ futures = {
337
+ executor.submit(process_instrument, pair, start_date): pair
338
+ for pair, start_date in instruments
339
+ }
340
+
341
+ for future in as_completed(futures):
342
+ pair = futures[future]
343
+ result = future.result()
344
+ print(f"{pair}: {result['months_added']} months added")
345
+ ```
346
+
347
+ ## Development
348
+
349
+ ### Setup
350
+
351
+ ```bash
352
+ # Clone repository
353
+ git clone https://github.com/Eon-Labs/exness-data-preprocess.git
354
+ cd exness-data-preprocess
355
+
356
+ # Install with development dependencies (using uv)
357
+ uv sync --dev
358
+
359
+ # Or with pip
360
+ pip install -e ".[dev]"
361
+ ```
362
+
363
+ ### Testing
364
+
365
+ ```bash
366
+ # Run all tests
367
+ uv run pytest
368
+
369
+ # Run with coverage
370
+ uv run pytest --cov=exness_data_preprocess --cov-report=html
371
+
372
+ # Run specific test
373
+ uv run pytest tests/test_processor.py -v
374
+ ```
375
+
376
+ ### Code Quality
377
+
378
+ ```bash
379
+ # Format code
380
+ uv run ruff format .
381
+
382
+ # Lint
383
+ uv run ruff check --fix .
384
+
385
+ # Type checking
386
+ uv run mypy src/
387
+ ```
388
+
389
+ ### Building
390
+
391
+ ```bash
392
+ # Build package
393
+ uv build
394
+
395
+ # Test installation locally
396
+ uv tool install --editable .
397
+ ```
398
+
399
+ ## Data Source
400
+
401
+ Data is sourced from Exness's public tick data repository:
402
+ - **URL**: https://ticks.ex2archive.com/
403
+ - **Format**: Monthly ZIP files with CSV tick data
404
+ - **Variants**: Raw_Spread (zero-spreads) + Standard (market spreads)
405
+ - **Content**: Timestamp, Bid, Ask prices for major forex pairs
406
+ - **Quality**: Institutional ECN/STP data with microsecond precision
407
+
408
+ ## Technical Specifications
409
+
410
+ ### Database Size (3-Year History, EURUSD)
411
+
412
+ | Metric | Value |
413
+ |--------|-------|
414
+ | Raw_Spread ticks | ~18.6M |
415
+ | Standard ticks | ~19.6M |
416
+ | OHLC bars (1m) | ~413K |
417
+ | Database size | ~2.08 GB |
418
+ | Date range | 2022-01-01 to 2025-01-10 |
419
+
420
+ ### Query Performance
421
+
422
+ | Operation | Time |
423
+ |-----------|------|
424
+ | Query 880K ticks (1 month) | <15ms |
425
+ | Query 1m OHLC (1 month) | <10ms |
426
+ | Resample to 1h (1 month) | <15ms |
427
+ | Resample to 1d (1 year) | <20ms |
428
+
429
+ ### Architecture Benefits
430
+
431
+ | Feature | Benefit |
432
+ |---------|---------|
433
+ | Single file per instrument | Unified storage, no file fragmentation |
434
+ | PRIMARY KEY constraints | Prevents duplicates during incremental updates |
435
+ | Automatic gap detection | Download only missing months |
436
+ | Dual-variant storage | Raw_Spread + Standard in same database |
437
+ | Phase7 OHLC schema | Dual spreads + dual tick counts |
438
+ | Date range queries | Efficient filtering without loading entire dataset |
439
+ | On-demand resampling | Any timeframe in <15ms |
440
+ | SQL filter support | Direct SQL WHERE clauses on ticks |
441
+
442
+ ## API Reference
443
+
444
+ ### ExnessDataProcessor
445
+
446
+ ```python
447
+ processor = edp.ExnessDataProcessor(base_dir="~/eon/exness-data")
448
+ ```
449
+
450
+ **Methods**:
451
+
452
+ - `update_data(pair, start_date, force_redownload=False, delete_zip=True)` - Update database with latest data
453
+ - `query_ohlc(pair, timeframe, start_date=None, end_date=None)` - Query OHLC bars
454
+ - `query_ticks(pair, variant, start_date=None, end_date=None, filter_sql=None)` - Query tick data
455
+ - `get_data_coverage(pair)` - Get coverage information
456
+
457
+ **Parameters**:
458
+
459
+ - `pair` (str): Currency pair (e.g., "EURUSD", "GBPUSD", "XAUUSD")
460
+ - `timeframe` (str): OHLC timeframe ("1m", "5m", "15m", "1h", "4h", "1d")
461
+ - `variant` (str): Tick variant ("raw_spread" or "standard")
462
+ - `start_date` (str): Start date in "YYYY-MM-DD" format
463
+ - `end_date` (str): End date in "YYYY-MM-DD" format
464
+ - `filter_sql` (str): SQL WHERE clause (e.g., "Bid > 1.11 AND Ask < 1.12")
465
+
466
+ ## Migration from v1.0.0
467
+
468
+ **v1.0.0 (Legacy)**:
469
+ - Monthly DuckDB files: `eurusd_ohlc_2024_08.duckdb`
470
+ - Parquet tick storage: `eurusd_ticks_2024_08.parquet`
471
+ - Functions: `process_month()`, `process_date_range()`, `analyze_ticks()`
472
+
473
+ **v2.0.0 (Current)**:
474
+ - Single DuckDB file: `eurusd.duckdb`
475
+ - No Parquet files (everything in DuckDB)
476
+ - Unified API: `processor.update_data()`, `processor.query_ohlc()`, `processor.query_ticks()`
477
+
478
+ **Migration Steps**:
479
+ 1. Run `processor.update_data(pair, start_date)` to create new unified database
480
+ 2. Delete old monthly files: `rm eurusd_ohlc_2024_*.duckdb eurusd_ticks_2024_*.parquet`
481
+ 3. Update code to use new API methods
482
+
483
+ ## License
484
+
485
+ MIT License - see LICENSE file for details.
486
+
487
+ ## Authors
488
+
489
+ - Terry Li <terry@eonlabs.com>
490
+ - Eon Labs
491
+
492
+ ## Contributing
493
+
494
+ Contributions are welcome! Please see CONTRIBUTING.md for guidelines.
495
+
496
+ ## Acknowledgments
497
+
498
+ - Exness for providing high-quality public tick data
499
+ - DuckDB for embedded OLAP capabilities with sub-15ms query performance
500
+
501
+ ## Additional Documentation
502
+
503
+ - **Basic Usage Examples**: See `examples/basic_usage.py`
504
+ - **Batch Processing**: See `examples/batch_processing.py`
505
+ - **Architecture Details**: See `docs/UNIFIED_DUCKDB_PLAN_v2.md`
506
+ - **Unit Tests**: See `tests/` directory
@@ -0,0 +1,10 @@
1
+ exness_data_preprocess/__init__.py,sha256=W2z4slZAQLWNrj83QNCiUg-z83vyasEI0DXFqjgxr0s,1342
2
+ exness_data_preprocess/api.py,sha256=gb1HUatHE4SqQ62uXM8j55oEDH_0lN7AqaoxSjuhAck,6764
3
+ exness_data_preprocess/cli.py,sha256=b3XOKF2cUO5E9D08rVRE3JRrxZr5UkbXsxijaaWR8A4,7059
4
+ exness_data_preprocess/processor.py,sha256=jSQ-cij56fZALOTAddsrtpJGOsBYYwJz_Ei6NsIa2P0,35653
5
+ exness_data_preprocess-0.1.0.dist-info/METADATA,sha256=DHG8t5T6kEAZVRb_13fxhOLNSuLabKVNtKFkCrpWR5M,15707
6
+ exness_data_preprocess-0.1.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
7
+ exness_data_preprocess-0.1.0.dist-info/entry_points.txt,sha256=2IoifK7DgeskCBuW-jmOaSMrcJQsmvRjxf6BK77hxk8,70
8
+ exness_data_preprocess-0.1.0.dist-info/licenses/AUTHORS.md,sha256=X8dzQz7qXtMBgCSynqdbiVqGU43nYswudSSW8njUXvA,511
9
+ exness_data_preprocess-0.1.0.dist-info/licenses/LICENSE,sha256=Tw9a0HzGThMjIXRkAR-0zL5azFsvGBaXZlornJKIXfE,1065
10
+ exness_data_preprocess-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.27.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ exness-preprocess = exness_data_preprocess.cli:main
@@ -0,0 +1,24 @@
1
+ # Authors
2
+
3
+ ## Project Lead
4
+
5
+ - **Terry Li** <terry@eonlabs.com>
6
+ - Original author and maintainer
7
+ - Architecture and core implementation
8
+
9
+ ## Organization
10
+
11
+ **Eon Labs**
12
+ - Website: https://eonlabs.com
13
+ - GitHub: https://github.com/Eon-Labs
14
+
15
+ ## Contributors
16
+
17
+ We welcome contributions! See CONTRIBUTING.md for guidelines.
18
+
19
+ ## Acknowledgments
20
+
21
+ - Exness for providing high-quality public tick data
22
+ - DuckDB team for embedded OLAP database
23
+ - Apache Arrow and Parquet communities
24
+ - Facebook's Zstd compression library
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Eon Labs
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.