zerodha-data-fetcher 1.0.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.
- zerodha_data_fetcher-1.0.0/LICENSE +0 -0
- zerodha_data_fetcher-1.0.0/MANIFEST.in +9 -0
- zerodha_data_fetcher-1.0.0/PKG-INFO +209 -0
- zerodha_data_fetcher-1.0.0/README.md +162 -0
- zerodha_data_fetcher-1.0.0/pyproject.toml +87 -0
- zerodha_data_fetcher-1.0.0/setup.cfg +4 -0
- zerodha_data_fetcher-1.0.0/setup.py +6 -0
- zerodha_data_fetcher-1.0.0/src/zerodha_data_fetcher/__init__.py +24 -0
- zerodha_data_fetcher-1.0.0/src/zerodha_data_fetcher/core/__init__.py +43 -0
- zerodha_data_fetcher-1.0.0/src/zerodha_data_fetcher/core/auth.py +101 -0
- zerodha_data_fetcher-1.0.0/src/zerodha_data_fetcher/core/data_fetcher.py +538 -0
- zerodha_data_fetcher-1.0.0/src/zerodha_data_fetcher/core/instrument_manager.py +283 -0
- zerodha_data_fetcher-1.0.0/src/zerodha_data_fetcher/core/rate_limiter.py +48 -0
- zerodha_data_fetcher-1.0.0/src/zerodha_data_fetcher/core/token_generator.py +204 -0
- zerodha_data_fetcher-1.0.0/src/zerodha_data_fetcher/utils/__init__.py +79 -0
- zerodha_data_fetcher-1.0.0/src/zerodha_data_fetcher/utils/config.py +163 -0
- zerodha_data_fetcher-1.0.0/src/zerodha_data_fetcher/utils/data/Kite_Instrument_ID.csv +86685 -0
- zerodha_data_fetcher-1.0.0/src/zerodha_data_fetcher/utils/data_loader.py +60 -0
- zerodha_data_fetcher-1.0.0/src/zerodha_data_fetcher/utils/encryption.py +86 -0
- zerodha_data_fetcher-1.0.0/src/zerodha_data_fetcher/utils/exceptions.py +31 -0
- zerodha_data_fetcher-1.0.0/src/zerodha_data_fetcher/utils/helpers.py +127 -0
- zerodha_data_fetcher-1.0.0/src/zerodha_data_fetcher/utils/logging_config.py +98 -0
- zerodha_data_fetcher-1.0.0/src/zerodha_data_fetcher.egg-info/PKG-INFO +209 -0
- zerodha_data_fetcher-1.0.0/src/zerodha_data_fetcher.egg-info/SOURCES.txt +25 -0
- zerodha_data_fetcher-1.0.0/src/zerodha_data_fetcher.egg-info/dependency_links.txt +1 -0
- zerodha_data_fetcher-1.0.0/src/zerodha_data_fetcher.egg-info/requires.txt +20 -0
- zerodha_data_fetcher-1.0.0/src/zerodha_data_fetcher.egg-info/top_level.txt +1 -0
|
Binary file
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
include README.md
|
|
2
|
+
include LICENSE
|
|
3
|
+
include pyproject.toml
|
|
4
|
+
include setup.py
|
|
5
|
+
recursive-include src/zerodha_data_fetcher *.py
|
|
6
|
+
recursive-include src/zerodha_data_fetcher/utils/data *.csv
|
|
7
|
+
recursive-include src/zerodha_data_fetcher/utils/data *.json
|
|
8
|
+
recursive-exclude * __pycache__
|
|
9
|
+
recursive-exclude * *.py[co]
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: zerodha-data-fetcher
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: A Python package for fetching historical data from Zerodha API
|
|
5
|
+
Author-email: Jayam Gupta <guptajayam47@gmail.com>
|
|
6
|
+
Maintainer-email: Jayam Gupta <guptajayam47@gmail.com>
|
|
7
|
+
License-Expression: MIT
|
|
8
|
+
Project-URL: Homepage, https://github.com/JayceeGupta/Zerodha-Data-Fetcher
|
|
9
|
+
Project-URL: Repository, https://github.com/JayceeGupta/Zerodha-Data-Fetcher
|
|
10
|
+
Project-URL: Documentation, https://github.com/JayceeGupta/Zerodha-Data-Fetcher#readme
|
|
11
|
+
Project-URL: Bug Tracker, https://github.com/JayceeGupta/Zerodha-Data-Fetcher/issues
|
|
12
|
+
Keywords: zerodha,trading,data,api,historical,stock-market
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Intended Audience :: Financial and Insurance Industry
|
|
16
|
+
Classifier: Operating System :: OS Independent
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
23
|
+
Classifier: Topic :: Office/Business :: Financial
|
|
24
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
25
|
+
Requires-Python: >=3.8
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
License-File: LICENSE
|
|
28
|
+
Requires-Dist: requests>=2.25.0
|
|
29
|
+
Requires-Dist: pandas>=1.3.0
|
|
30
|
+
Requires-Dist: python-dateutil>=2.8.0
|
|
31
|
+
Requires-Dist: pyotp>=2.6.0
|
|
32
|
+
Requires-Dist: keyring>=23.0.0
|
|
33
|
+
Requires-Dist: cryptography>=3.4.0
|
|
34
|
+
Requires-Dist: Brotli>=1.0.9
|
|
35
|
+
Provides-Extra: dev
|
|
36
|
+
Requires-Dist: pytest>=6.0; extra == "dev"
|
|
37
|
+
Requires-Dist: pytest-cov>=2.0; extra == "dev"
|
|
38
|
+
Requires-Dist: black>=21.0; extra == "dev"
|
|
39
|
+
Requires-Dist: flake8>=3.9; extra == "dev"
|
|
40
|
+
Requires-Dist: mypy>=0.910; extra == "dev"
|
|
41
|
+
Requires-Dist: pre-commit>=2.15; extra == "dev"
|
|
42
|
+
Provides-Extra: docs
|
|
43
|
+
Requires-Dist: sphinx>=4.0; extra == "docs"
|
|
44
|
+
Requires-Dist: sphinx-rtd-theme>=1.0; extra == "docs"
|
|
45
|
+
Requires-Dist: myst-parser>=0.15; extra == "docs"
|
|
46
|
+
Dynamic: license-file
|
|
47
|
+
|
|
48
|
+
# Zerodha Data Fetcher
|
|
49
|
+
|
|
50
|
+
A Python package for fetching historical data from Zerodha API with advanced features like rate limiting, authentication management, and parallel data fetching.
|
|
51
|
+
|
|
52
|
+
## Features
|
|
53
|
+
|
|
54
|
+
- 🚀 **Fast Parallel Data Fetching**: Concurrent requests with intelligent rate limiting
|
|
55
|
+
- 🔐 **Automatic Authentication**: Handles login, 2FA, and token management
|
|
56
|
+
- 📊 **Multiple Data Formats**: Support for minute, daily, and other timeframes
|
|
57
|
+
- 🛡️ **Error Handling**: Robust error handling with retry mechanisms
|
|
58
|
+
- 🔍 **Symbol Search**: Built-in instrument search and validation
|
|
59
|
+
- ⚙️ **Configurable**: Flexible configuration via environment variables or parameters
|
|
60
|
+
|
|
61
|
+
## Installation
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
pip install zerodha-data-fetcher
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Quick Start
|
|
68
|
+
|
|
69
|
+
### 1. Set up environment variables
|
|
70
|
+
|
|
71
|
+
Create a `.env` file in your project root:
|
|
72
|
+
|
|
73
|
+
```env
|
|
74
|
+
ZERODHA_USER_ID=your_user_id
|
|
75
|
+
ZERODHA_PASSWORD=your_password
|
|
76
|
+
ZERODHA_USER_TYPE=individual
|
|
77
|
+
ZERODHA_TOTP_SECRET=your_totp_secret
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### 2. Basic Usage
|
|
81
|
+
|
|
82
|
+
```python
|
|
83
|
+
from zerodha_data_fetcher import ZerodhaDataFetcher
|
|
84
|
+
from datetime import date, timedelta
|
|
85
|
+
|
|
86
|
+
# Initialize the fetcher
|
|
87
|
+
fetcher = ZerodhaDataFetcher(requests_per_second=2)
|
|
88
|
+
|
|
89
|
+
# Fetch historical data
|
|
90
|
+
end_date = date.today()
|
|
91
|
+
start_date = end_date - timedelta(days=30)
|
|
92
|
+
|
|
93
|
+
# Using symbol (recommended)
|
|
94
|
+
data = fetcher.fetch_historical_data(
|
|
95
|
+
ticker_token="RELIANCE",
|
|
96
|
+
start_date=start_date,
|
|
97
|
+
end_date=end_date,
|
|
98
|
+
timeframe="minute"
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
# Using instrument token
|
|
102
|
+
data = fetcher.fetch_historical_data(
|
|
103
|
+
ticker_token=408065, # HDFC Bank
|
|
104
|
+
start_date=start_date,
|
|
105
|
+
end_date=end_date,
|
|
106
|
+
timeframe="minute"
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
print(data.head())
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### 3. Advanced Usage
|
|
113
|
+
|
|
114
|
+
```python
|
|
115
|
+
# Custom configuration
|
|
116
|
+
fetcher = ZerodhaDataFetcher(
|
|
117
|
+
requests_per_second=3,
|
|
118
|
+
token_expiry_hours=6,
|
|
119
|
+
user_id="custom_user_id", # Override env var
|
|
120
|
+
password="custom_password" # Override env var
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
# Search for symbols
|
|
124
|
+
results = fetcher.search_symbols("HDFC", limit=5)
|
|
125
|
+
print(results)
|
|
126
|
+
|
|
127
|
+
# Get instrument info
|
|
128
|
+
info = fetcher.get_instrument_info("RELIANCE")
|
|
129
|
+
print(info)
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## Configuration
|
|
133
|
+
|
|
134
|
+
### Environment Variables
|
|
135
|
+
|
|
136
|
+
| Variable | Description | Required |
|
|
137
|
+
| ---------------------------------- | ----------------------------------- | -------- |
|
|
138
|
+
| `ZERODHA_USER_ID` | Your Zerodha user ID | Yes |
|
|
139
|
+
| `ZERODHA_PASSWORD` | Your Zerodha password | Yes |
|
|
140
|
+
| `ZERODHA_USER_TYPE` | Account type (individual/corporate) | Yes |
|
|
141
|
+
| `ZERODHA_TOTP_SECRET` | TOTP secret for 2FA | Yes |
|
|
142
|
+
| `ZERODHA_KEYRING_TOKEN_KEY` | Keyring token key | No |
|
|
143
|
+
| `ZERODHA_KEYRING_ENCRYPTION_KEY` | Keyring encryption key | No |
|
|
144
|
+
|
|
145
|
+
### Parameters
|
|
146
|
+
|
|
147
|
+
- `requests_per_second`: API rate limit (1-10, default: 2)
|
|
148
|
+
- `token_expiry_hours`: Token validity period (default: 6)
|
|
149
|
+
- `timeframe`: Data timeframe ('minute', 'day', etc.)
|
|
150
|
+
|
|
151
|
+
## API Reference
|
|
152
|
+
|
|
153
|
+
### ZerodhaDataFetcher
|
|
154
|
+
|
|
155
|
+
Main class for fetching historical data.
|
|
156
|
+
|
|
157
|
+
#### Methods
|
|
158
|
+
|
|
159
|
+
- `fetch_historical_data(ticker_token, start_date, end_date, timeframe='minute')`: Fetch historical data
|
|
160
|
+
- `search_symbols(partial_name, limit=10)`: Search for trading symbols
|
|
161
|
+
- `get_instrument_info(symbol)`: Get instrument information
|
|
162
|
+
|
|
163
|
+
## Error Handling
|
|
164
|
+
|
|
165
|
+
The package includes comprehensive error handling:
|
|
166
|
+
|
|
167
|
+
```python
|
|
168
|
+
from zerodha_data_fetcher.utils.exceptions import (
|
|
169
|
+
ZerodhaAPIError,
|
|
170
|
+
AuthenticationError,
|
|
171
|
+
InvalidTickerError,
|
|
172
|
+
DataFetchError
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
try:
|
|
176
|
+
data = fetcher.fetch_historical_data("INVALID", start_date, end_date)
|
|
177
|
+
except InvalidTickerError as e:
|
|
178
|
+
print(f"Invalid ticker: {e}")
|
|
179
|
+
except AuthenticationError as e:
|
|
180
|
+
print(f"Auth failed: {e}")
|
|
181
|
+
except DataFetchError as e:
|
|
182
|
+
print(f"Data fetch failed: {e}")
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## Contributing
|
|
186
|
+
|
|
187
|
+
1. Fork the repository
|
|
188
|
+
2. Create a feature branch
|
|
189
|
+
3. Make your changes
|
|
190
|
+
4. Add tests
|
|
191
|
+
5. Submit a pull request
|
|
192
|
+
|
|
193
|
+
## License
|
|
194
|
+
|
|
195
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
196
|
+
|
|
197
|
+
## Disclaimer
|
|
198
|
+
|
|
199
|
+
This package is for educational and research purposes. Please ensure compliance with Zerodha's terms of service and applicable regulations when using this package.
|
|
200
|
+
|
|
201
|
+
## Support
|
|
202
|
+
|
|
203
|
+
- 📖 [Documentation](https://github.com/JayceeGupta/Zerodha-Data-Fetcher#readme)
|
|
204
|
+
- 🐛 [Bug Reports](https://github.com/JayceeGupta/Zerodha-Data-Fetcher/issues)
|
|
205
|
+
- 💬 [Discussions](https://github.com/JayceeGupta/Zerodha-Data-Fetcher/discussions)
|
|
206
|
+
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
```
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
# Zerodha Data Fetcher
|
|
2
|
+
|
|
3
|
+
A Python package for fetching historical data from Zerodha API with advanced features like rate limiting, authentication management, and parallel data fetching.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 🚀 **Fast Parallel Data Fetching**: Concurrent requests with intelligent rate limiting
|
|
8
|
+
- 🔐 **Automatic Authentication**: Handles login, 2FA, and token management
|
|
9
|
+
- 📊 **Multiple Data Formats**: Support for minute, daily, and other timeframes
|
|
10
|
+
- 🛡️ **Error Handling**: Robust error handling with retry mechanisms
|
|
11
|
+
- 🔍 **Symbol Search**: Built-in instrument search and validation
|
|
12
|
+
- ⚙️ **Configurable**: Flexible configuration via environment variables or parameters
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
pip install zerodha-data-fetcher
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Quick Start
|
|
21
|
+
|
|
22
|
+
### 1. Set up environment variables
|
|
23
|
+
|
|
24
|
+
Create a `.env` file in your project root:
|
|
25
|
+
|
|
26
|
+
```env
|
|
27
|
+
ZERODHA_USER_ID=your_user_id
|
|
28
|
+
ZERODHA_PASSWORD=your_password
|
|
29
|
+
ZERODHA_USER_TYPE=individual
|
|
30
|
+
ZERODHA_TOTP_SECRET=your_totp_secret
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### 2. Basic Usage
|
|
34
|
+
|
|
35
|
+
```python
|
|
36
|
+
from zerodha_data_fetcher import ZerodhaDataFetcher
|
|
37
|
+
from datetime import date, timedelta
|
|
38
|
+
|
|
39
|
+
# Initialize the fetcher
|
|
40
|
+
fetcher = ZerodhaDataFetcher(requests_per_second=2)
|
|
41
|
+
|
|
42
|
+
# Fetch historical data
|
|
43
|
+
end_date = date.today()
|
|
44
|
+
start_date = end_date - timedelta(days=30)
|
|
45
|
+
|
|
46
|
+
# Using symbol (recommended)
|
|
47
|
+
data = fetcher.fetch_historical_data(
|
|
48
|
+
ticker_token="RELIANCE",
|
|
49
|
+
start_date=start_date,
|
|
50
|
+
end_date=end_date,
|
|
51
|
+
timeframe="minute"
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
# Using instrument token
|
|
55
|
+
data = fetcher.fetch_historical_data(
|
|
56
|
+
ticker_token=408065, # HDFC Bank
|
|
57
|
+
start_date=start_date,
|
|
58
|
+
end_date=end_date,
|
|
59
|
+
timeframe="minute"
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
print(data.head())
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### 3. Advanced Usage
|
|
66
|
+
|
|
67
|
+
```python
|
|
68
|
+
# Custom configuration
|
|
69
|
+
fetcher = ZerodhaDataFetcher(
|
|
70
|
+
requests_per_second=3,
|
|
71
|
+
token_expiry_hours=6,
|
|
72
|
+
user_id="custom_user_id", # Override env var
|
|
73
|
+
password="custom_password" # Override env var
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
# Search for symbols
|
|
77
|
+
results = fetcher.search_symbols("HDFC", limit=5)
|
|
78
|
+
print(results)
|
|
79
|
+
|
|
80
|
+
# Get instrument info
|
|
81
|
+
info = fetcher.get_instrument_info("RELIANCE")
|
|
82
|
+
print(info)
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Configuration
|
|
86
|
+
|
|
87
|
+
### Environment Variables
|
|
88
|
+
|
|
89
|
+
| Variable | Description | Required |
|
|
90
|
+
| ---------------------------------- | ----------------------------------- | -------- |
|
|
91
|
+
| `ZERODHA_USER_ID` | Your Zerodha user ID | Yes |
|
|
92
|
+
| `ZERODHA_PASSWORD` | Your Zerodha password | Yes |
|
|
93
|
+
| `ZERODHA_USER_TYPE` | Account type (individual/corporate) | Yes |
|
|
94
|
+
| `ZERODHA_TOTP_SECRET` | TOTP secret for 2FA | Yes |
|
|
95
|
+
| `ZERODHA_KEYRING_TOKEN_KEY` | Keyring token key | No |
|
|
96
|
+
| `ZERODHA_KEYRING_ENCRYPTION_KEY` | Keyring encryption key | No |
|
|
97
|
+
|
|
98
|
+
### Parameters
|
|
99
|
+
|
|
100
|
+
- `requests_per_second`: API rate limit (1-10, default: 2)
|
|
101
|
+
- `token_expiry_hours`: Token validity period (default: 6)
|
|
102
|
+
- `timeframe`: Data timeframe ('minute', 'day', etc.)
|
|
103
|
+
|
|
104
|
+
## API Reference
|
|
105
|
+
|
|
106
|
+
### ZerodhaDataFetcher
|
|
107
|
+
|
|
108
|
+
Main class for fetching historical data.
|
|
109
|
+
|
|
110
|
+
#### Methods
|
|
111
|
+
|
|
112
|
+
- `fetch_historical_data(ticker_token, start_date, end_date, timeframe='minute')`: Fetch historical data
|
|
113
|
+
- `search_symbols(partial_name, limit=10)`: Search for trading symbols
|
|
114
|
+
- `get_instrument_info(symbol)`: Get instrument information
|
|
115
|
+
|
|
116
|
+
## Error Handling
|
|
117
|
+
|
|
118
|
+
The package includes comprehensive error handling:
|
|
119
|
+
|
|
120
|
+
```python
|
|
121
|
+
from zerodha_data_fetcher.utils.exceptions import (
|
|
122
|
+
ZerodhaAPIError,
|
|
123
|
+
AuthenticationError,
|
|
124
|
+
InvalidTickerError,
|
|
125
|
+
DataFetchError
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
try:
|
|
129
|
+
data = fetcher.fetch_historical_data("INVALID", start_date, end_date)
|
|
130
|
+
except InvalidTickerError as e:
|
|
131
|
+
print(f"Invalid ticker: {e}")
|
|
132
|
+
except AuthenticationError as e:
|
|
133
|
+
print(f"Auth failed: {e}")
|
|
134
|
+
except DataFetchError as e:
|
|
135
|
+
print(f"Data fetch failed: {e}")
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## Contributing
|
|
139
|
+
|
|
140
|
+
1. Fork the repository
|
|
141
|
+
2. Create a feature branch
|
|
142
|
+
3. Make your changes
|
|
143
|
+
4. Add tests
|
|
144
|
+
5. Submit a pull request
|
|
145
|
+
|
|
146
|
+
## License
|
|
147
|
+
|
|
148
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
149
|
+
|
|
150
|
+
## Disclaimer
|
|
151
|
+
|
|
152
|
+
This package is for educational and research purposes. Please ensure compliance with Zerodha's terms of service and applicable regulations when using this package.
|
|
153
|
+
|
|
154
|
+
## Support
|
|
155
|
+
|
|
156
|
+
- 📖 [Documentation](https://github.com/JayceeGupta/Zerodha-Data-Fetcher#readme)
|
|
157
|
+
- 🐛 [Bug Reports](https://github.com/JayceeGupta/Zerodha-Data-Fetcher/issues)
|
|
158
|
+
- 💬 [Discussions](https://github.com/JayceeGupta/Zerodha-Data-Fetcher/discussions)
|
|
159
|
+
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
```
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "zerodha-data-fetcher"
|
|
7
|
+
version = "1.0.0"
|
|
8
|
+
description = "A Python package for fetching historical data from Zerodha API"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
license-files = ["LICENSE"]
|
|
12
|
+
authors = [
|
|
13
|
+
{name = "Jayam Gupta", email = "guptajayam47@gmail.com"}
|
|
14
|
+
]
|
|
15
|
+
maintainers = [
|
|
16
|
+
{name = "Jayam Gupta", email = "guptajayam47@gmail.com"}
|
|
17
|
+
]
|
|
18
|
+
keywords = ["zerodha", "trading", "data", "api", "historical", "stock-market"]
|
|
19
|
+
classifiers = [
|
|
20
|
+
"Development Status :: 4 - Beta",
|
|
21
|
+
"Intended Audience :: Developers",
|
|
22
|
+
"Intended Audience :: Financial and Insurance Industry",
|
|
23
|
+
"Operating System :: OS Independent",
|
|
24
|
+
"Programming Language :: Python :: 3",
|
|
25
|
+
"Programming Language :: Python :: 3.8",
|
|
26
|
+
"Programming Language :: Python :: 3.9",
|
|
27
|
+
"Programming Language :: Python :: 3.10",
|
|
28
|
+
"Programming Language :: Python :: 3.11",
|
|
29
|
+
"Programming Language :: Python :: 3.12",
|
|
30
|
+
"Topic :: Office/Business :: Financial",
|
|
31
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
32
|
+
]
|
|
33
|
+
requires-python = ">=3.8"
|
|
34
|
+
dependencies = [
|
|
35
|
+
"requests>=2.25.0",
|
|
36
|
+
"pandas>=1.3.0",
|
|
37
|
+
"python-dateutil>=2.8.0",
|
|
38
|
+
"pyotp>=2.6.0",
|
|
39
|
+
"keyring>=23.0.0",
|
|
40
|
+
"cryptography>=3.4.0",
|
|
41
|
+
"Brotli>=1.0.9",
|
|
42
|
+
]
|
|
43
|
+
|
|
44
|
+
[project.optional-dependencies]
|
|
45
|
+
dev = [
|
|
46
|
+
"pytest>=6.0",
|
|
47
|
+
"pytest-cov>=2.0",
|
|
48
|
+
"black>=21.0",
|
|
49
|
+
"flake8>=3.9",
|
|
50
|
+
"mypy>=0.910",
|
|
51
|
+
"pre-commit>=2.15",
|
|
52
|
+
]
|
|
53
|
+
docs = [
|
|
54
|
+
"sphinx>=4.0",
|
|
55
|
+
"sphinx-rtd-theme>=1.0",
|
|
56
|
+
"myst-parser>=0.15",
|
|
57
|
+
]
|
|
58
|
+
|
|
59
|
+
[project.urls]
|
|
60
|
+
Homepage = "https://github.com/JayceeGupta/Zerodha-Data-Fetcher"
|
|
61
|
+
Repository = "https://github.com/JayceeGupta/Zerodha-Data-Fetcher"
|
|
62
|
+
Documentation = "https://github.com/JayceeGupta/Zerodha-Data-Fetcher#readme"
|
|
63
|
+
"Bug Tracker" = "https://github.com/JayceeGupta/Zerodha-Data-Fetcher/issues"
|
|
64
|
+
|
|
65
|
+
[tool.setuptools.packages.find]
|
|
66
|
+
where = ["src"]
|
|
67
|
+
|
|
68
|
+
[tool.setuptools.package-data]
|
|
69
|
+
zerodha_data_fetcher = ["utils/data/*.csv", "utils/data/*.json"]
|
|
70
|
+
|
|
71
|
+
[tool.black]
|
|
72
|
+
line-length = 88
|
|
73
|
+
target-version = ['py38']
|
|
74
|
+
include = '\.pyi?$'
|
|
75
|
+
|
|
76
|
+
[tool.mypy]
|
|
77
|
+
python_version = "3.8"
|
|
78
|
+
warn_return_any = true
|
|
79
|
+
warn_unused_configs = true
|
|
80
|
+
disallow_untyped_defs = true
|
|
81
|
+
|
|
82
|
+
[tool.pytest.ini_options]
|
|
83
|
+
testpaths = ["tests"]
|
|
84
|
+
python_files = ["test_*.py"]
|
|
85
|
+
python_classes = ["Test*"]
|
|
86
|
+
python_functions = ["test_*"]
|
|
87
|
+
addopts = "-v --cov=zerodha_data_fetcher --cov-report=html --cov-report=term-missing"
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"""Zerodha Data Fetcher - A Python package for fetching historical data from Zerodha API."""
|
|
2
|
+
|
|
3
|
+
__version__ = "1.0.0"
|
|
4
|
+
__author__ = "Your Name"
|
|
5
|
+
__email__ = "your.email@example.com"
|
|
6
|
+
|
|
7
|
+
# Import main classes and functions for easy access
|
|
8
|
+
try:
|
|
9
|
+
from .core.data_fetcher import ZerodhaDataFetcher, fetchDataZerodha
|
|
10
|
+
from .utils.logging_config import setup_logging
|
|
11
|
+
from .utils.config import Config
|
|
12
|
+
|
|
13
|
+
__all__ = [
|
|
14
|
+
"ZerodhaDataFetcher",
|
|
15
|
+
"fetchDataZerodha",
|
|
16
|
+
"setup_logging",
|
|
17
|
+
"Config",
|
|
18
|
+
"__version__"
|
|
19
|
+
]
|
|
20
|
+
except ImportError as e:
|
|
21
|
+
# Handle import errors gracefully during development
|
|
22
|
+
import warnings
|
|
23
|
+
warnings.warn(f"Some imports failed: {e}")
|
|
24
|
+
__all__ = ["__version__"]
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# """Core functionality for Zerodha Data Fetcher."""
|
|
2
|
+
|
|
3
|
+
# from .data_fetcher import ZerodhaDataFetcher
|
|
4
|
+
# from .auth import AuthenticationManager
|
|
5
|
+
# from .token_generator import ZerodhaTokenGenerator, getEncAuthToken, get_TOTP
|
|
6
|
+
# from .instrument_manager import ZerodhaInstrumentManager, fetchZerodhaID
|
|
7
|
+
# from .rate_limiter import RateLimitedThreadPoolExecutor
|
|
8
|
+
|
|
9
|
+
# __all__ = [
|
|
10
|
+
# "ZerodhaDataFetcher",
|
|
11
|
+
# "AuthenticationManager",
|
|
12
|
+
# "ZerodhaTokenGenerator",
|
|
13
|
+
# "ZerodhaInstrumentManager",
|
|
14
|
+
# "RateLimitedThreadPoolExecutor",
|
|
15
|
+
# "getEncAuthToken", # Backward compatibility
|
|
16
|
+
# "get_TOTP", # Backward compatibility
|
|
17
|
+
# "fetchZerodhaID" # Backward compatibility
|
|
18
|
+
# ]
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
"""
|
|
22
|
+
Core modules for Zerodha Data Fetcher.
|
|
23
|
+
|
|
24
|
+
This module contains the main functionality:
|
|
25
|
+
- Data fetching and processing
|
|
26
|
+
- Authentication management
|
|
27
|
+
- Rate limiting
|
|
28
|
+
- Instrument management
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
from .data_fetcher import ZerodhaDataFetcher, fetchDataZerodha
|
|
32
|
+
from .instrument_manager import ZerodhaInstrumentManager, fetchZerodhaID
|
|
33
|
+
from .auth import AuthenticationManager
|
|
34
|
+
from .rate_limiter import RateLimitedThreadPoolExecutor
|
|
35
|
+
|
|
36
|
+
__all__ = [
|
|
37
|
+
"ZerodhaDataFetcher",
|
|
38
|
+
"fetchDataZerodha",
|
|
39
|
+
"ZerodhaInstrumentManager",
|
|
40
|
+
"fetchZerodhaID",
|
|
41
|
+
"AuthenticationManager",
|
|
42
|
+
"RateLimitedThreadPoolExecutor",
|
|
43
|
+
]
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"""Authentication management for Zerodha API."""
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
import time
|
|
5
|
+
import logging
|
|
6
|
+
from datetime import date
|
|
7
|
+
from typing import Optional
|
|
8
|
+
|
|
9
|
+
import keyring
|
|
10
|
+
|
|
11
|
+
from ..utils.config import Config
|
|
12
|
+
from ..utils.exceptions import AuthenticationError, TokenExpiredError
|
|
13
|
+
from ..utils.encryption import TokenEncryption
|
|
14
|
+
from .token_generator import ZerodhaTokenGenerator
|
|
15
|
+
|
|
16
|
+
logger = logging.getLogger(__name__)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class AuthenticationManager:
|
|
20
|
+
"""Manages authentication tokens for Zerodha API."""
|
|
21
|
+
|
|
22
|
+
def __init__(self, token_expiry_hours: float = Config.DEFAULT_TOKEN_EXPIRY_HOURS, config: Optional['Config'] = None):
|
|
23
|
+
self.token_expiry_hours = token_expiry_hours
|
|
24
|
+
self.config = config or Config()
|
|
25
|
+
self.token_key = self.config.ZERODHA_KEYRING_TOKEN_KEY
|
|
26
|
+
self.token_generator = ZerodhaTokenGenerator(config=self.config)
|
|
27
|
+
|
|
28
|
+
def get_auth_token(self) -> str:
|
|
29
|
+
"""
|
|
30
|
+
Retrieves an authentication token for accessing the Zerodha API.
|
|
31
|
+
|
|
32
|
+
Returns:
|
|
33
|
+
str: The authentication token.
|
|
34
|
+
|
|
35
|
+
Raises:
|
|
36
|
+
AuthenticationError: If token generation fails.
|
|
37
|
+
"""
|
|
38
|
+
try:
|
|
39
|
+
expiry_seconds = self.token_expiry_hours * 3600
|
|
40
|
+
today = date.today().strftime('%Y-%m-%d')
|
|
41
|
+
current_time = time.time()
|
|
42
|
+
|
|
43
|
+
logger.debug(f"Getting auth token for date: {today}")
|
|
44
|
+
|
|
45
|
+
# Try to retrieve stored token
|
|
46
|
+
encrypted_token = keyring.get_password(self.token_key, "token")
|
|
47
|
+
token_date = keyring.get_password(self.token_key, "date")
|
|
48
|
+
token_timestamp = keyring.get_password(self.token_key, "timestamp")
|
|
49
|
+
|
|
50
|
+
if encrypted_token and token_date and token_timestamp:
|
|
51
|
+
logger.info("Found token data in keyring")
|
|
52
|
+
time_elapsed = current_time - float(token_timestamp)
|
|
53
|
+
logger.info(f"Time elapsed since last token: {time_elapsed} seconds")
|
|
54
|
+
logger.info(f"Token expiry time: {expiry_seconds} seconds")
|
|
55
|
+
if token_date == today and time_elapsed < expiry_seconds:
|
|
56
|
+
logger.info("Found valid token for today")
|
|
57
|
+
return TokenEncryption.decrypt_token(encrypted_token)
|
|
58
|
+
else:
|
|
59
|
+
logger.debug("Stored token is outdated")
|
|
60
|
+
else:
|
|
61
|
+
logger.debug("No valid token data found in keyring")
|
|
62
|
+
|
|
63
|
+
except Exception as e:
|
|
64
|
+
logger.error(f"Error retrieving token: {str(e)}")
|
|
65
|
+
|
|
66
|
+
# Generate new token
|
|
67
|
+
return self._generate_new_token()
|
|
68
|
+
|
|
69
|
+
def _generate_new_token(self) -> str:
|
|
70
|
+
"""Generate and store a new authentication token."""
|
|
71
|
+
logger.info("Generating new auth token")
|
|
72
|
+
|
|
73
|
+
try:
|
|
74
|
+
new_token = self.token_generator.generate_auth_token()
|
|
75
|
+
encrypted_token = TokenEncryption.encrypt_token(new_token)
|
|
76
|
+
|
|
77
|
+
# Store the new token
|
|
78
|
+
today = date.today().strftime('%Y-%m-%d')
|
|
79
|
+
current_time = time.time()
|
|
80
|
+
|
|
81
|
+
keyring.set_password(self.token_key, "token", encrypted_token)
|
|
82
|
+
keyring.set_password(self.token_key, "date", today)
|
|
83
|
+
keyring.set_password(self.token_key, "timestamp", str(current_time))
|
|
84
|
+
keyring.set_password(self.token_key, "userid", self.config.get_user_id())
|
|
85
|
+
|
|
86
|
+
logger.info("Successfully saved new token to keyring")
|
|
87
|
+
return new_token
|
|
88
|
+
|
|
89
|
+
except Exception as e:
|
|
90
|
+
logger.error(f"Failed to generate/save token: {str(e)}")
|
|
91
|
+
raise AuthenticationError(f"Token generation failed: {str(e)}")
|
|
92
|
+
|
|
93
|
+
def invalidate_token(self) -> None:
|
|
94
|
+
"""Invalidate the current stored token."""
|
|
95
|
+
try:
|
|
96
|
+
keyring.delete_password(self.token_key, "token")
|
|
97
|
+
keyring.delete_password(self.token_key, "date")
|
|
98
|
+
keyring.delete_password(self.token_key, "timestamp")
|
|
99
|
+
logger.info("Token invalidated successfully")
|
|
100
|
+
except Exception as e:
|
|
101
|
+
logger.warning(f"Failed to invalidate token: {str(e)}")
|