pfeed 0.0.1.dev1__tar.gz → 0.0.1.dev2__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 (78) hide show
  1. {pfeed-0.0.1.dev1 → pfeed-0.0.1.dev2}/LICENSE +1 -1
  2. pfeed-0.0.1.dev2/PKG-INFO +141 -0
  3. pfeed-0.0.1.dev2/README.md +107 -0
  4. pfeed-0.0.1.dev2/pfeed/__init__.py +16 -0
  5. pfeed-0.0.1.dev2/pfeed/cli/__init__.py +4 -0
  6. pfeed-0.0.1.dev2/pfeed/cli/commands/__init__.py +0 -0
  7. pfeed-0.0.1.dev2/pfeed/cli/commands/config.py +67 -0
  8. pfeed-0.0.1.dev2/pfeed/cli/commands/docker_compose.py +27 -0
  9. pfeed-0.0.1.dev2/pfeed/cli/commands/download.py +44 -0
  10. pfeed-0.0.1.dev2/pfeed/cli/commands/stream.py +0 -0
  11. pfeed-0.0.1.dev2/pfeed/cli/main.py +24 -0
  12. {pfeed-0.0.1.dev1 → pfeed-0.0.1.dev2}/pfeed/config/logging.yml +1 -1
  13. pfeed-0.0.1.dev2/pfeed/config_handler.py +57 -0
  14. pfeed-0.0.1.dev2/pfeed/const/commons.py +6 -0
  15. pfeed-0.0.1.dev2/pfeed/const/paths.py +16 -0
  16. {pfeed-0.0.1.dev1 → pfeed-0.0.1.dev2}/pfeed/datastore.py +2 -4
  17. {pfeed-0.0.1.dev1 → pfeed-0.0.1.dev2}/pfeed/feeds/bybit_feed.py +5 -1
  18. {pfeed-0.0.1.dev1 → pfeed-0.0.1.dev2}/pfeed/filepath.py +2 -2
  19. pfeed-0.0.1.dev2/pfeed/main.py +10 -0
  20. pfeed-0.0.1.dev2/pfeed/sources/bybit/__init__.py +2 -0
  21. {pfeed-0.0.1.dev1 → pfeed-0.0.1.dev2}/pfeed/sources/bybit/const.py +2 -2
  22. pfeed-0.0.1.dev1/pfeed/sources/bybit/historical.py → pfeed-0.0.1.dev2/pfeed/sources/bybit/download.py +63 -59
  23. {pfeed-0.0.1.dev1 → pfeed-0.0.1.dev2}/pfeed/sources/bybit/eda.ipynb +73 -1
  24. pfeed-0.0.1.dev2/pfeed/sources/bybit/stream.py +6 -0
  25. {pfeed-0.0.1.dev1 → pfeed-0.0.1.dev2}/pfeed/utils/utils.py +6 -4
  26. pfeed-0.0.1.dev2/pfeed/utils/validate.py +30 -0
  27. pfeed-0.0.1.dev2/pyproject.toml +50 -0
  28. pfeed-0.0.1.dev1/PKG-INFO +0 -42
  29. pfeed-0.0.1.dev1/README.md +0 -17
  30. pfeed-0.0.1.dev1/pfeed/.DS_Store +0 -0
  31. pfeed-0.0.1.dev1/pfeed/__init__.py +0 -20
  32. pfeed-0.0.1.dev1/pfeed/const/__pycache__/__init__.cpython-310.pyc +0 -0
  33. pfeed-0.0.1.dev1/pfeed/const/__pycache__/commons.cpython-310.pyc +0 -0
  34. pfeed-0.0.1.dev1/pfeed/const/__pycache__/commons.cpython-311.pyc +0 -0
  35. pfeed-0.0.1.dev1/pfeed/const/__pycache__/paths.cpython-310.pyc +0 -0
  36. pfeed-0.0.1.dev1/pfeed/const/__pycache__/paths.cpython-311.pyc +0 -0
  37. pfeed-0.0.1.dev1/pfeed/const/commons.py +0 -2
  38. pfeed-0.0.1.dev1/pfeed/const/paths.py +0 -9
  39. pfeed-0.0.1.dev1/pfeed/feeds/__pycache__/__init__.cpython-310.pyc +0 -0
  40. pfeed-0.0.1.dev1/pfeed/feeds/__pycache__/__init__.cpython-311.pyc +0 -0
  41. pfeed-0.0.1.dev1/pfeed/feeds/__pycache__/base_feed.cpython-310.pyc +0 -0
  42. pfeed-0.0.1.dev1/pfeed/feeds/__pycache__/base_feed.cpython-311.pyc +0 -0
  43. pfeed-0.0.1.dev1/pfeed/feeds/__pycache__/bybit_feed.cpython-310.pyc +0 -0
  44. pfeed-0.0.1.dev1/pfeed/feeds/__pycache__/bybit_feed.cpython-311.pyc +0 -0
  45. pfeed-0.0.1.dev1/pfeed/feeds/__pycache__/yahoo_finance_feed.cpython-310.pyc +0 -0
  46. pfeed-0.0.1.dev1/pfeed/feeds/__pycache__/yahoo_finance_feed.cpython-311.pyc +0 -0
  47. pfeed-0.0.1.dev1/pfeed/main.py +0 -72
  48. pfeed-0.0.1.dev1/pfeed/sources/.DS_Store +0 -0
  49. pfeed-0.0.1.dev1/pfeed/sources/__pycache__/__init__.cpython-310.pyc +0 -0
  50. pfeed-0.0.1.dev1/pfeed/sources/__pycache__/__init__.cpython-311.pyc +0 -0
  51. pfeed-0.0.1.dev1/pfeed/sources/bybit/__init__.py +0 -2
  52. pfeed-0.0.1.dev1/pfeed/sources/bybit/__pycache__/__init__.cpython-310.pyc +0 -0
  53. pfeed-0.0.1.dev1/pfeed/sources/bybit/__pycache__/__init__.cpython-311.pyc +0 -0
  54. pfeed-0.0.1.dev1/pfeed/sources/bybit/__pycache__/api.cpython-310.pyc +0 -0
  55. pfeed-0.0.1.dev1/pfeed/sources/bybit/__pycache__/api.cpython-311.pyc +0 -0
  56. pfeed-0.0.1.dev1/pfeed/sources/bybit/__pycache__/bybit_feed.cpython-310.pyc +0 -0
  57. pfeed-0.0.1.dev1/pfeed/sources/bybit/__pycache__/bytewax_temp.cpython-310.pyc +0 -0
  58. pfeed-0.0.1.dev1/pfeed/sources/bybit/__pycache__/const.cpython-310.pyc +0 -0
  59. pfeed-0.0.1.dev1/pfeed/sources/bybit/__pycache__/const.cpython-311.pyc +0 -0
  60. pfeed-0.0.1.dev1/pfeed/sources/bybit/__pycache__/data_source.cpython-310.pyc +0 -0
  61. pfeed-0.0.1.dev1/pfeed/sources/bybit/__pycache__/elt.cpython-310.pyc +0 -0
  62. pfeed-0.0.1.dev1/pfeed/sources/bybit/__pycache__/etl.cpython-310.pyc +0 -0
  63. pfeed-0.0.1.dev1/pfeed/sources/bybit/__pycache__/etl.cpython-311.pyc +0 -0
  64. pfeed-0.0.1.dev1/pfeed/sources/bybit/__pycache__/historical.cpython-310.pyc +0 -0
  65. pfeed-0.0.1.dev1/pfeed/sources/bybit/__pycache__/historical.cpython-311.pyc +0 -0
  66. pfeed-0.0.1.dev1/pfeed/sources/bybit/__pycache__/streaming.cpython-310.pyc +0 -0
  67. pfeed-0.0.1.dev1/pfeed/sources/bybit/__pycache__/streaming.cpython-311.pyc +0 -0
  68. pfeed-0.0.1.dev1/pfeed/sources/bybit/config.yml +0 -4
  69. pfeed-0.0.1.dev1/pfeed/utils/__pycache__/utils.cpython-310.pyc +0 -0
  70. pfeed-0.0.1.dev1/pfeed/utils/__pycache__/utils.cpython-311.pyc +0 -0
  71. pfeed-0.0.1.dev1/pyproject.toml +0 -33
  72. {pfeed-0.0.1.dev1 → pfeed-0.0.1.dev2}/pfeed/feeds/__init__.py +0 -0
  73. {pfeed-0.0.1.dev1 → pfeed-0.0.1.dev2}/pfeed/feeds/base_feed.py +0 -0
  74. {pfeed-0.0.1.dev1 → pfeed-0.0.1.dev2}/pfeed/feeds/custom_csv_feed.py +0 -0
  75. {pfeed-0.0.1.dev1 → pfeed-0.0.1.dev2}/pfeed/feeds/yahoo_finance_feed.py +0 -0
  76. {pfeed-0.0.1.dev1 → pfeed-0.0.1.dev2}/pfeed/sources/__init__.py +0 -0
  77. {pfeed-0.0.1.dev1 → pfeed-0.0.1.dev2}/pfeed/sources/bybit/api.py +0 -0
  78. {pfeed-0.0.1.dev1 → pfeed-0.0.1.dev2}/pfeed/sources/bybit/etl.py +0 -0
@@ -186,7 +186,7 @@
186
186
  same "printed page" as the copyright notice for easier
187
187
  identification within third-party archives.
188
188
 
189
- Copyright [yyyy] [name of copyright owner]
189
+ Copyright [2024] [Stephen Yau, PFund.ai]
190
190
 
191
191
  Licensed under the Apache License, Version 2.0 (the "License");
192
192
  you may not use this file except in compliance with the License.
@@ -0,0 +1,141 @@
1
+ Metadata-Version: 2.1
2
+ Name: pfeed
3
+ Version: 0.0.1.dev2
4
+ Summary: Data pipeline for algo-trading, getting and storing both real-time and historical data made easy.
5
+ Home-page: https://pfund.ai
6
+ License: Apache-2.0
7
+ Keywords: trading,algo-trading,data pipeline,ETL,data lake,data warehouse,data integration,historical data,live data,data streaming
8
+ Author: Stephen Yau
9
+ Author-email: softwareentrepreneer+pfeed@gmail.com
10
+ Requires-Python: >=3.10,<4.0
11
+ Classifier: License :: OSI Approved :: Apache Software License
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.10
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Requires-Dist: beautifulsoup4 (>=4.12.3,<5.0.0)
17
+ Requires-Dist: click (>=8.1.7,<9.0.0)
18
+ Requires-Dist: minio (>=7.2.3,<8.0.0)
19
+ Requires-Dist: orjson (>=3.9.12,<4.0.0)
20
+ Requires-Dist: pandas (>=2.2.0,<3.0.0)
21
+ Requires-Dist: pfund (>=0.0.1.dev2,<0.0.2)
22
+ Requires-Dist: platformdirs (>=4.2.0,<5.0.0)
23
+ Requires-Dist: pyarrow (>=15.0.0,<16.0.0)
24
+ Requires-Dist: python-dotenv (>=1.0.1,<2.0.0)
25
+ Requires-Dist: pyyaml (>=6.0.1,<7.0.0)
26
+ Requires-Dist: ray (>=2.9.1,<3.0.0)
27
+ Requires-Dist: requests (>=2.31.0,<3.0.0)
28
+ Requires-Dist: rich (>=13.7.0,<14.0.0)
29
+ Requires-Dist: tqdm (>=4.66.1,<5.0.0)
30
+ Requires-Dist: yfinance (>=0.2.36,<0.3.0)
31
+ Project-URL: Documentation, https://pfund.ai/docs
32
+ Project-URL: Repository, https://github.com/PFund-Software-Ltd/pfeed
33
+ Description-Content-Type: text/markdown
34
+
35
+ # PFeed: Data Pipeline for Algo-Trading, Getting and Storing Real-Time and Historical Data Made Easy.
36
+
37
+ [![Poetry](https://img.shields.io/endpoint?url=https://python-poetry.org/badge/v0.json)](https://python-poetry.org/)
38
+ [![PyPI](https://img.shields.io/pypi/v/pfeed.svg)](https://pypi.org/project/pfeed)
39
+ ![PyPI - Support Python Versions](https://img.shields.io/pypi/pyversions/pfeed)
40
+
41
+ PFeed (/piː fiːd/) is a data integration library tailored for algorithmic trading,
42
+ serving as an ETL (Extract, Transform, Load) data pipeline between raw data sources and traders,
43
+ helping them in creating a local data lake for quantitative research.
44
+
45
+ PFeed allows traders to download historical, paper, and live data from various data sources, both free and paid,
46
+ and stores them into a local data lake using [MinIO](https://min.io/).
47
+
48
+ It is designed to be used alongside [PFund](https://github.com/PFund-Software-Ltd/pfund) — A Complete Algo-Trading Framework for Machine Learning, TradFi, CeFi and DeFi ready. Supports Vectorized and Event-Driven Backtesting, Paper and Live Trading.
49
+
50
+ <details>
51
+ <summary>Table of Contents</summary>
52
+
53
+ - [Project Status](#project-status)
54
+ - [Mission](#mission)
55
+ - [Core Features](#core-features)
56
+ - [Installation](#installation)
57
+ - [Quick Start](#quick-start)
58
+ - [Download Historical Data on Command Line](#download-historical-data-on-command-line)
59
+ - [Download Historical Data in Python](#download-historical-data-in-python)
60
+ - [Supported Data Sources](#supported-data-sources)
61
+ - [Related Projects](#related-projects)
62
+
63
+ </details>
64
+
65
+
66
+ ## Project Status
67
+ **_Caution: PFeed is at a VERY EARLY stage, use it at your own risk._**
68
+
69
+ PFeed is currently under active development, the framework design will be prioritized first over
70
+ stability and scalability.
71
+
72
+ Please note that the available version is a *dev* version, not a *stable* one. \
73
+ You are encouraged to play with the *dev* version, but only use it when a *stable* version is released.
74
+
75
+ > PFeed for the time being only supports [Bybit](https://bybit.com/) and Yahoo Finance for testing purpose.
76
+
77
+ ## Mission
78
+ Algo-trading has always been a complicated task due to the multitude of components and procedures involved. \
79
+ Data collection and processing is probably the most mundane and yet critical part of it, as all results and findings
80
+ are derived from the data.
81
+
82
+ However, preparing this data for use is not quick and easy. For example, sometimes even when the data is available (e.g. [Bybit data](https://public.bybit.com/trading/)), it is often in raw form and requires some cleaning.
83
+
84
+ > PFeed's mission is to **_free traders from the tedious data work_** by providing cleaned data in a standard format that is ready for use, making them significantly faster to get to the analysis and strategy development phase.
85
+
86
+
87
+ ## Core Features
88
+ - [x] Unified approach for interacting with various data sources, obtaining historical and real-time data
89
+ - [x] ETL data pipline for transforming raw data and storing it in [MinIO](https://min.io/) (optional)
90
+ - [x] Utilizes [Ray](https://github.com/ray-project/ray) for parallel data downloading
91
+ - [ ] Integrates with [Prefect](https://www.prefect.io) to control data flows
92
+ - [ ] Listens to PFund's trade engine and adds trade history to a local database [Timescaledb](https://www.timescale.com/) (optional)
93
+
94
+
95
+ ## Installation
96
+ ### Using [Poetry](https://python-poetry.org) (Recommended)
97
+ > If you don't have poetry installed, please visit https://python-poetry.org/docs/
98
+ ```bash
99
+ poetry add pfeed
100
+ ```
101
+
102
+ ### Using Pip
103
+ ```bash
104
+ pip install pfeed
105
+ ```
106
+
107
+
108
+ ## Quick Start
109
+ ### Download Historical Data on Command Line
110
+ ```bash
111
+ pfeed download -s bybit -p BTC_USDT_PERP --no-minio
112
+ ```
113
+
114
+ ### Download Historical Data in Python
115
+ ```python
116
+ from pfeed import bybit
117
+ bybit.download(pdts=['BTC_USDT_PERP'])
118
+ ```
119
+
120
+
121
+ ## Supported Data Sources
122
+ | Data Source | Get Historical Data | Download Historical Data | Get Live/Paper Data | Download Live/Paper Data |
123
+ | -------------------------------------------- | ------------------- | ------------------------ | ------------------- | ------------------------ |
124
+ | Yahoo Finance | 🟢 | ⚪ | ⚪ | ⚪ |
125
+ | Bybit | 🟢 | 🟢 | 🟡 | 🔴 |
126
+ | *Interactive Brokers (IB) | 🔴 | ⚪ | 🔴 | 🔴 |
127
+ | *[FirstRate Data](https://firstratedata.com) | 🔴 | 🔴 | ⚪ | ⚪ |
128
+ | Binance | 🔴 | 🔴 | 🔴 | 🔴 |
129
+ | OKX | 🔴 | 🔴 | 🔴 | 🔴 |
130
+
131
+ 🟢 = finished \
132
+ 🟡 = in progress \
133
+ 🔴 = todo \
134
+ ⚪ = not applicable \
135
+ \* = paid data \
136
+ get data = store it in memory for python to use \
137
+ download data = store it in local machine for later research
138
+
139
+
140
+ ## Related Projects
141
+ - [PFund](https://github.com/PFund-Software-Ltd/pfund) — A Complete Algo-Trading Framework for Machine Learning, TradFi, CeFi and DeFi ready. Supports Vectorized and Event-Driven Backtesting, Paper and Live Trading
@@ -0,0 +1,107 @@
1
+ # PFeed: Data Pipeline for Algo-Trading, Getting and Storing Real-Time and Historical Data Made Easy.
2
+
3
+ [![Poetry](https://img.shields.io/endpoint?url=https://python-poetry.org/badge/v0.json)](https://python-poetry.org/)
4
+ [![PyPI](https://img.shields.io/pypi/v/pfeed.svg)](https://pypi.org/project/pfeed)
5
+ ![PyPI - Support Python Versions](https://img.shields.io/pypi/pyversions/pfeed)
6
+
7
+ PFeed (/piː fiːd/) is a data integration library tailored for algorithmic trading,
8
+ serving as an ETL (Extract, Transform, Load) data pipeline between raw data sources and traders,
9
+ helping them in creating a local data lake for quantitative research.
10
+
11
+ PFeed allows traders to download historical, paper, and live data from various data sources, both free and paid,
12
+ and stores them into a local data lake using [MinIO](https://min.io/).
13
+
14
+ It is designed to be used alongside [PFund](https://github.com/PFund-Software-Ltd/pfund) — A Complete Algo-Trading Framework for Machine Learning, TradFi, CeFi and DeFi ready. Supports Vectorized and Event-Driven Backtesting, Paper and Live Trading.
15
+
16
+ <details>
17
+ <summary>Table of Contents</summary>
18
+
19
+ - [Project Status](#project-status)
20
+ - [Mission](#mission)
21
+ - [Core Features](#core-features)
22
+ - [Installation](#installation)
23
+ - [Quick Start](#quick-start)
24
+ - [Download Historical Data on Command Line](#download-historical-data-on-command-line)
25
+ - [Download Historical Data in Python](#download-historical-data-in-python)
26
+ - [Supported Data Sources](#supported-data-sources)
27
+ - [Related Projects](#related-projects)
28
+
29
+ </details>
30
+
31
+
32
+ ## Project Status
33
+ **_Caution: PFeed is at a VERY EARLY stage, use it at your own risk._**
34
+
35
+ PFeed is currently under active development, the framework design will be prioritized first over
36
+ stability and scalability.
37
+
38
+ Please note that the available version is a *dev* version, not a *stable* one. \
39
+ You are encouraged to play with the *dev* version, but only use it when a *stable* version is released.
40
+
41
+ > PFeed for the time being only supports [Bybit](https://bybit.com/) and Yahoo Finance for testing purpose.
42
+
43
+ ## Mission
44
+ Algo-trading has always been a complicated task due to the multitude of components and procedures involved. \
45
+ Data collection and processing is probably the most mundane and yet critical part of it, as all results and findings
46
+ are derived from the data.
47
+
48
+ However, preparing this data for use is not quick and easy. For example, sometimes even when the data is available (e.g. [Bybit data](https://public.bybit.com/trading/)), it is often in raw form and requires some cleaning.
49
+
50
+ > PFeed's mission is to **_free traders from the tedious data work_** by providing cleaned data in a standard format that is ready for use, making them significantly faster to get to the analysis and strategy development phase.
51
+
52
+
53
+ ## Core Features
54
+ - [x] Unified approach for interacting with various data sources, obtaining historical and real-time data
55
+ - [x] ETL data pipline for transforming raw data and storing it in [MinIO](https://min.io/) (optional)
56
+ - [x] Utilizes [Ray](https://github.com/ray-project/ray) for parallel data downloading
57
+ - [ ] Integrates with [Prefect](https://www.prefect.io) to control data flows
58
+ - [ ] Listens to PFund's trade engine and adds trade history to a local database [Timescaledb](https://www.timescale.com/) (optional)
59
+
60
+
61
+ ## Installation
62
+ ### Using [Poetry](https://python-poetry.org) (Recommended)
63
+ > If you don't have poetry installed, please visit https://python-poetry.org/docs/
64
+ ```bash
65
+ poetry add pfeed
66
+ ```
67
+
68
+ ### Using Pip
69
+ ```bash
70
+ pip install pfeed
71
+ ```
72
+
73
+
74
+ ## Quick Start
75
+ ### Download Historical Data on Command Line
76
+ ```bash
77
+ pfeed download -s bybit -p BTC_USDT_PERP --no-minio
78
+ ```
79
+
80
+ ### Download Historical Data in Python
81
+ ```python
82
+ from pfeed import bybit
83
+ bybit.download(pdts=['BTC_USDT_PERP'])
84
+ ```
85
+
86
+
87
+ ## Supported Data Sources
88
+ | Data Source | Get Historical Data | Download Historical Data | Get Live/Paper Data | Download Live/Paper Data |
89
+ | -------------------------------------------- | ------------------- | ------------------------ | ------------------- | ------------------------ |
90
+ | Yahoo Finance | 🟢 | ⚪ | ⚪ | ⚪ |
91
+ | Bybit | 🟢 | 🟢 | 🟡 | 🔴 |
92
+ | *Interactive Brokers (IB) | 🔴 | ⚪ | 🔴 | 🔴 |
93
+ | *[FirstRate Data](https://firstratedata.com) | 🔴 | 🔴 | ⚪ | ⚪ |
94
+ | Binance | 🔴 | 🔴 | 🔴 | 🔴 |
95
+ | OKX | 🔴 | 🔴 | 🔴 | 🔴 |
96
+
97
+ 🟢 = finished \
98
+ 🟡 = in progress \
99
+ 🔴 = todo \
100
+ ⚪ = not applicable \
101
+ \* = paid data \
102
+ get data = store it in memory for python to use \
103
+ download data = store it in local machine for later research
104
+
105
+
106
+ ## Related Projects
107
+ - [PFund](https://github.com/PFund-Software-Ltd/pfund) — A Complete Algo-Trading Framework for Machine Learning, TradFi, CeFi and DeFi ready. Supports Vectorized and Event-Driven Backtesting, Paper and Live Trading
@@ -0,0 +1,16 @@
1
+ from pfeed.config_handler import configure
2
+ from pfeed.sources import bybit
3
+ from pfeed.feeds import YahooFinanceFeed, BybitFeed
4
+ from importlib.metadata import version
5
+
6
+
7
+ __version__ = version('pfeed')
8
+
9
+
10
+ __all__ = (
11
+ '__version__',
12
+ 'configure',
13
+ 'bybit',
14
+ 'YahooFinanceFeed',
15
+ 'BybitFeed',
16
+ )
@@ -0,0 +1,4 @@
1
+ from pfeed.cli.main import pfeed_group
2
+
3
+
4
+ __all__ = ["pfeed_group"]
File without changes
@@ -0,0 +1,67 @@
1
+ import os
2
+ import sys
3
+ import yaml
4
+ from pathlib import Path
5
+ from pprint import pformat
6
+
7
+ import click
8
+
9
+ from pfeed.const.paths import USER_CONFIG_FILE_PATH
10
+ from pfeed.config_handler import ConfigHandler
11
+
12
+
13
+ def load_config(config_file_path: str | Path):
14
+ config_file_path = Path(config_file_path)
15
+ if config_file_path.is_file():
16
+ with open(config_file_path, 'r') as f:
17
+ return yaml.safe_load(f) or {}
18
+ return {}
19
+
20
+
21
+ def save_config(config: ConfigHandler, config_file_path: str | Path):
22
+ with open(config_file_path, 'w') as f:
23
+ yaml.dump(config.__dict__, f, default_flow_style=False)
24
+
25
+
26
+ def remove_config(config_file_path: str | Path):
27
+ config_file_path = Path(config_file_path)
28
+ if config_file_path.is_file():
29
+ os.remove(config_file_path)
30
+
31
+
32
+ @click.group(invoke_without_command=True)
33
+ @click.pass_context
34
+ @click.option('--data-path', type=click.Path(), help='Set the data path')
35
+ @click.option('--log-path', type=click.Path(), help='Set the log path')
36
+ @click.option('--logging-path', 'logging_config_file_path', type=click.Path(exists=True), help='Set the logging config file path')
37
+ @click.option('--logging-config', type=dict, help='Set the logging config')
38
+ @click.option('--use-fork-process', type=bool, help='If True, multiprocessing.set_start_method("fork")')
39
+ @click.option('--use-custom-excepthook', type=bool, help='If True, log uncaught exceptions to file')
40
+ def config(ctx, **kwargs):
41
+ """Configures pfeed settings."""
42
+ # if theres command invoked after config (e.g. pfeed config reset), skip this
43
+ if ctx.invoked_subcommand:
44
+ return
45
+
46
+ config: ConfigHandler = ctx.obj['config']
47
+
48
+ # Filter out options that were not provided by the user
49
+ provided_options = {k: v for k, v in kwargs.items() if v is not None}
50
+
51
+ # prints out current config if no options are provided
52
+ if not provided_options:
53
+ click.echo(f"PFeed's config:\n{pformat(config.__dict__)}")
54
+ else:
55
+ for option, value in provided_options.items():
56
+ setattr(config, option, value)
57
+ click.echo(f"{option} set to: {value}")
58
+
59
+ save_config(config, USER_CONFIG_FILE_PATH)
60
+ click.echo(f"config saved to {USER_CONFIG_FILE_PATH}.")
61
+
62
+
63
+ @config.command()
64
+ def reset():
65
+ """Resets the application configuration by removing the existing configuration file."""
66
+ remove_config(USER_CONFIG_FILE_PATH)
67
+ click.echo("Configuration successfully reset.")
@@ -0,0 +1,27 @@
1
+ from pathlib import Path
2
+ import importlib.resources
3
+ import subprocess
4
+
5
+ from dotenv import find_dotenv
6
+ import click
7
+
8
+ from pfeed.const.paths import PROJ_NAME
9
+
10
+
11
+ @click.command(context_settings=dict(
12
+ ignore_unknown_options=True,
13
+ allow_extra_args=True,
14
+ ))
15
+ @click.pass_context
16
+ def docker_compose(ctx):
17
+ """Forwards commands to docker-compose with the package's docker-compose.yml file."""
18
+ package_dir = Path(importlib.resources.files(PROJ_NAME)).resolve().parents[0]
19
+ env_file_path = find_dotenv(usecwd=True, raise_error_if_not_found=True)
20
+ click.echo(f'env file: {env_file_path}')
21
+ docker_compose_file = package_dir / 'docker-compose.yml'
22
+
23
+ command = ['docker-compose', '-f', str(docker_compose_file)] + ctx.args
24
+ subprocess.run(command)
25
+
26
+
27
+
@@ -0,0 +1,44 @@
1
+ import importlib
2
+
3
+ import click
4
+
5
+ from pfeed.utils.validate import validate_pdts_and_ptypes
6
+ from pfeed.const.commons import ALIASES, SUPPORTED_DOWNLOAD_DATA_SOURCES, SUPPORTED_DATA_TYPES
7
+
8
+
9
+ # add aliases to supported download data sources
10
+ SUPPORTED_DOWNLOAD_DATA_SOURCES_ALIASES_INCLUDED = SUPPORTED_DOWNLOAD_DATA_SOURCES + [k for k, v in ALIASES.items() if v in SUPPORTED_DOWNLOAD_DATA_SOURCES]
11
+
12
+
13
+ @click.command()
14
+ @click.pass_context
15
+ @click.option('-s', '--source', required=True, type=click.Choice(SUPPORTED_DOWNLOAD_DATA_SOURCES_ALIASES_INCLUDED, case_sensitive=False), help='Data source')
16
+ @click.option('-p', '--pdts', multiple=True, default=[], help='List of trading products')
17
+ @click.option('--dtypes', '--dt', multiple=True, type=click.Choice(SUPPORTED_DATA_TYPES, case_sensitive=False), help='List of data types, e.g. raw, tick, second, minute, hour, daily')
18
+ @click.option('--ptypes', '--pt', multiple=True, default=[], help='List of product types, e.g. PERP = get all perpetuals')
19
+ @click.option('-b', '--start-date', type=click.DateTime(formats=["%Y-%m-%d"]), help='Start date in YYYY-MM-DD format')
20
+ @click.option('-n', '--end-date', type=click.DateTime(formats=["%Y-%m-%d"]), help='End date in YYYY-MM-DD format')
21
+ @click.option('--batch-size', default=8, type=int, help='batch size for Ray tasks') # REVIEW
22
+ @click.option('--no-ray', is_flag=True)
23
+ @click.option('--no-minio', is_flag=True)
24
+ def download(ctx, source, pdts, dtypes, ptypes, start_date, end_date, batch_size, no_ray, no_minio):
25
+ if source in ALIASES:
26
+ source = ALIASES[source]
27
+ pdts = [pdt.replace('-', '_') for pdt in pdts]
28
+ validate_pdts_and_ptypes(source, pdts, ptypes, is_cli=True)
29
+ if start_date:
30
+ start_date = start_date.date()
31
+ if end_date:
32
+ end_date = end_date.date()
33
+ pipeline = importlib.import_module(f'pfeed.sources.{source.lower()}.download')
34
+ pipeline.run(
35
+ pdts=list(pdts),
36
+ dtypes=list(dtypes),
37
+ ptypes=list(ptypes),
38
+ start_date=start_date,
39
+ end_date=end_date,
40
+ batch_size=batch_size,
41
+ use_ray=not no_ray,
42
+ use_minio=not no_minio,
43
+ config=ctx.obj['config'],
44
+ )
File without changes
@@ -0,0 +1,24 @@
1
+ import click
2
+
3
+ from pfeed.config_handler import ConfigHandler
4
+ from pfeed.const.paths import USER_CONFIG_FILE_PATH
5
+ from pfeed.cli.commands.docker_compose import docker_compose
6
+ from pfeed.cli.commands.config import config, load_config
7
+ from pfeed.cli.commands.download import download
8
+ # from pfeed.cli.commands.stream import stream
9
+
10
+
11
+ @click.group(context_settings={"help_option_names": ["-h", "--help"]})
12
+ @click.pass_context
13
+ @click.version_option()
14
+ def pfeed_group(ctx):
15
+ """PFeed's CLI"""
16
+ ctx.ensure_object(dict)
17
+ config: dict = load_config(USER_CONFIG_FILE_PATH)
18
+ ctx.obj['config'] = ConfigHandler(**config)
19
+
20
+
21
+ pfeed_group.add_command(docker_compose)
22
+ pfeed_group.add_command(config)
23
+ pfeed_group.add_command(download)
24
+ # pfeed_group.add_command(stream)
@@ -27,7 +27,7 @@ handlers:
27
27
  level: 'DEBUG'
28
28
  formatter: 'file'
29
29
  compressed_timed_rotating_file_handler:
30
- class: 'pfund.logging.handlers.CompressedTimedRotatingFileHandler'
30
+ class: 'pfund.plogging.handlers.CompressedTimedRotatingFileHandler'
31
31
  level: 'DEBUG'
32
32
  formatter: 'file'
33
33
  kwargs: {'when': 'midnight', 'backupCount': 7, 'utc': True, 'encoding': 'utf-8'}
@@ -0,0 +1,57 @@
1
+ import os
2
+ import sys
3
+ import multiprocessing
4
+ import logging
5
+ from types import TracebackType
6
+ from dataclasses import dataclass
7
+
8
+ from pfeed.const.paths import PROJ_NAME, PROJ_CONFIG_PATH, LOG_PATH, DATA_PATH
9
+
10
+
11
+ def _custom_excepthook(exception_class: type[BaseException], exception: BaseException, traceback: TracebackType):
12
+ '''Catches any uncaught exceptions and logs them'''
13
+ # sys.__excepthook__(exception_class, exception, traceback)
14
+ try:
15
+ raise exception
16
+ except:
17
+ logging.getLogger(PROJ_NAME).exception('Uncaught exception:')
18
+
19
+
20
+ @dataclass
21
+ class ConfigHandler:
22
+ data_path: str = str(DATA_PATH)
23
+ log_path: str = str(LOG_PATH)
24
+ logging_config_file_path: str = f'{PROJ_CONFIG_PATH}/logging.yml'
25
+ logging_config: dict | None = None
26
+ use_fork_process: bool = True
27
+ use_custom_excepthook: bool = True
28
+
29
+ def __post_init__(self):
30
+ for path in [self.data_path]:
31
+ if not os.path.exists(path):
32
+ os.makedirs(path)
33
+ print(f'created {path}')
34
+
35
+ if self.use_fork_process and sys.platform != 'win32':
36
+ multiprocessing.set_start_method('fork', force=True)
37
+
38
+ if self.use_custom_excepthook:
39
+ sys.excepthook = _custom_excepthook
40
+
41
+
42
+ def configure(
43
+ data_path: str = str(DATA_PATH),
44
+ log_path: str = str(LOG_PATH),
45
+ logging_config_file_path: str = f'{PROJ_CONFIG_PATH}/logging.yml',
46
+ logging_config: dict | None=None,
47
+ use_fork_process: bool=True,
48
+ use_custom_excepthook: bool=True,
49
+ ):
50
+ return ConfigHandler(
51
+ data_path=data_path,
52
+ log_path=log_path,
53
+ logging_config_file_path=logging_config_file_path,
54
+ logging_config=logging_config,
55
+ use_fork_process=use_fork_process,
56
+ use_custom_excepthook=use_custom_excepthook,
57
+ )
@@ -0,0 +1,6 @@
1
+ SUPPORTED_DATA_TYPES = ['raw', 'tick', 'second', 'minute', 'hour', 'daily']
2
+ SUPPORTED_DATA_FEEDS = ['YAHOO_FINANCE', 'BYBIT']
3
+ SUPPORTED_DOWNLOAD_DATA_SOURCES = ['BYBIT']
4
+ ALIASES = {
5
+ 'YF': 'YAHOO_FINANCE',
6
+ }
@@ -0,0 +1,16 @@
1
+ from pathlib import Path
2
+ from platformdirs import user_log_dir, user_data_dir, user_config_dir
3
+
4
+
5
+ # project paths
6
+ PROJ_NAME = Path(__file__).resolve().parents[2].name
7
+ MAIN_PATH = Path(__file__).resolve().parents[3]
8
+ PROJ_PATH = MAIN_PATH / PROJ_NAME / PROJ_NAME
9
+ PROJ_CONFIG_PATH = PROJ_PATH / 'config'
10
+
11
+
12
+ # user paths
13
+ LOG_PATH = Path(user_log_dir()) / PROJ_NAME
14
+ DATA_PATH = Path(user_data_dir()) / PROJ_NAME
15
+ USER_CONFIG_PATH = Path(user_config_dir()) / PROJ_NAME
16
+ USER_CONFIG_FILE_PATH = USER_CONFIG_PATH / f'{PROJ_NAME}_config.yml'
@@ -7,8 +7,6 @@ from typing import Generator
7
7
  from minio import Minio, S3Error
8
8
  from minio.api import ObjectWriteResult
9
9
 
10
- from pfeed.const.paths import PROJ_NAME
11
-
12
10
 
13
11
  logger = logging.getLogger('minio')
14
12
 
@@ -16,11 +14,11 @@ logger = logging.getLogger('minio')
16
14
  # EXTEND, currently only consider using MinIO
17
15
  class Datastore:
18
16
  DATA_PART_SIZE = 5 * (1024 ** 2) # part size for S3, 5 MB
19
- BUCKET_NAME = PROJ_NAME + '-' + os.getenv('PFEED_ENV', 'DEV').lower()
17
+ BUCKET_NAME = 'pfeed' + '-' + os.getenv('PFEED_ENV', 'DEV').lower()
20
18
 
21
19
  def __init__(self, **kwargs):
22
20
  self.minio = Minio(
23
- endpoint=os.getenv('MINIO_ENDPOINT'),
21
+ endpoint=os.getenv('MINIO_HOST')+':'+os.getenv('MINIO_PORT', '9000'),
24
22
  access_key=os.getenv('MINIO_ACCESS_KEY'),
25
23
  secret_key=os.getenv('MINIO_SECRET_KEY'),
26
24
  # turn off TLS, i.e. not using HTTPS
@@ -85,7 +85,11 @@ class BybitFeed(BaseFeed):
85
85
  df = pd.read_parquet(io.BytesIO(resampled_data))
86
86
  dfs.append(df)
87
87
  return pd.concat(dfs)
88
-
88
+
89
+ # TODO?: maybe useful if used as a standalone program, not useful at all if used with PFund
90
+ def get_real_time_data(self, env='LIVE'):
91
+ pass
92
+
89
93
 
90
94
  if __name__ == '__main__':
91
95
  feed = BybitFeed()
@@ -25,9 +25,9 @@ class FilePath:
25
25
  self.data_type = self.dtype = data_type.lower()
26
26
  self.mode = mode
27
27
  self.pdt = pdt.lower()
28
- self.date = date
28
+ self.date = str(date)
29
29
  self.file_extension = file_extension
30
- self.filename = create_filename(pdt.upper(), date, file_extension)
30
+ self.filename = create_filename(pdt.upper(), self.date, file_extension)
31
31
  self.storage_Path = self.sPath = Path(self.env) / self.data_source / self.mode / self.dtype / pdt.upper() / self.filename
32
32
  self.storage_path = self.spath = str(self.storage_Path)
33
33
  self.file_Path = self.fPath = self.data_Path / self.storage_Path
@@ -0,0 +1,10 @@
1
+ from pfeed.cli import pfeed_group
2
+
3
+
4
+ def run_cli() -> None:
5
+ """Application Entrypoint."""
6
+ pfeed_group(obj={})
7
+
8
+
9
+ if __name__ == '__main__':
10
+ run_cli()
@@ -0,0 +1,2 @@
1
+ from pfeed.sources.bybit.download import download_historical_data as download
2
+ from pfeed.sources.bybit.stream import stream_real_time_data as stream
@@ -1,7 +1,7 @@
1
1
  DATA_SOURCE = 'BYBIT'
2
2
  # EXTEND: support FUT and IFUT
3
- # SUPPORTED_CRYPTO_PRODUCT_TYPES = ['SPOT', 'PERP', 'IPERP', 'FUT', 'IFUT']
4
- SUPPORTED_CRYPTO_PRODUCT_TYPES = ['SPOT', 'PERP', 'IPERP']
3
+ # SUPPORTED_PRODUCT_TYPES = ['SPOT', 'PERP', 'IPERP', 'FUT', 'IFUT']
4
+ SUPPORTED_PRODUCT_TYPES = ['SPOT', 'PERP', 'IPERP']
5
5
  RAW_DATA_TYPE = 'tick'
6
6
  # do not need to be precise
7
7
  DATA_START_DATE = '2020-01-01'