Skip to content

Commit d3ddf1f

Browse files
committed
Added ability to dynamically register a custom data source class
1 parent ae42c79 commit d3ddf1f

File tree

4 files changed

+237
-56
lines changed

4 files changed

+237
-56
lines changed

README.md

Lines changed: 168 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,18 @@
33

44
# Financial data sources (fin-ds)
55

6-
Financial Data Sources (fin-ds) is a Python package for retrieving financial OHLCV data from a data source using a common interface and returning a standardized pandas DataFrame. Using the library is as simple as:
6+
`fin-ds` (financial data sources) is a Python package for retrieving financial OHLCV data from a data source using a common interface and returning a standardized pandas DataFrame. Using the library is as simple as:
77

88
```python
9-
ds = DataSourceFactory("Tinngo")
9+
ds = DataSourceFactory("Tiingo")
1010
df = df.get_ticker_data("AAPL")
1111
```
1212

13+
To see the list of available data sources call `DataSourceFactory.data_sources`:
14+
```python
15+
['AlphaVantage', 'EODHD', 'NasdaqDataLink', 'Tiingo', 'YFinance']
16+
```
17+
1318
Here are the column mappings from each data source into fin-ds:
1419
| fin-ds | Alpha Vantage | EODHD | Nasdaq | Tiingo | Yahoo Finance |
1520
| :--- | :--- | :--- | :--- | :--- | :--- |
@@ -32,6 +37,8 @@ Here are the column mappings from each data source into fin-ds:
3237

3338
## Overview
3439

40+
`fin-ds` is a Python package designed to simplify the process of fetching financial OHLCV (Open, High, Low, Close, Volume) data from various sources through a unified interface. It abstracts away the differences between data source APIs, returning data in a standardized pandas DataFrame format. This makes it an ideal tool for financial analysis, algorithmic trading strategy development, and data science projects focusing on financial markets.
41+
3542

3643
## Getting started
3744

@@ -72,17 +79,176 @@ At this point in time, there are no exposed configuration options.
7279

7380
## Usage
7481

82+
### Built-in data sources
83+
The package comes with a variety of built-in data sources that can be easily accessed and used to fetch data. To use a built-in data source, simply instantiate the DataSourceFactory with the name of the data source you wish to use.
84+
85+
Example:
86+
```python
87+
from fin_ds import DataSourceFactory
88+
89+
# Create an instance of the AlphaVantage data source
90+
alpha_vantage_ds = DataSourceFactory("AlphaVantage")
91+
92+
# Now you can use the data source instance to fetch data
93+
data = alpha_vantage_ds.get_ticker_data("AAPL")
94+
```
95+
96+
The available built-in data sources include:
97+
98+
* AlphaVantage
99+
* EODHD
100+
* NasdaqDataLink
101+
* Tiingo
102+
* YFinance
103+
104+
You can list all available data sources using:
105+
```python
106+
print(DataSourceFactory.data_sources)
107+
```
108+
109+
### Custom Data Sources
110+
111+
To extend the functionality with your own data sources, you can create custom data source classes and register them with the `DataSourceFactory`. Custom data source classes should subclass `BaseDataSource` and implement the required methods.
112+
113+
#### Creating a Custom Data Source
114+
115+
1. **Subclass `BaseDataSource`**: Your custom data source class should inherit from `BaseDataSource`.
116+
117+
2. **Implement Required Methods**: At a minimum, your class should implement the `get_ticker_data` method.
118+
119+
#### Example:
120+
121+
```python
122+
from fin_ds.data_sources.base_data_source import BaseDataSource
123+
import pandas as pd
124+
125+
class MyCustomDataSource(BaseDataSource):
126+
def get_ticker_data(self, ticker, interval="daily"):
127+
# Custom logic to fetch data
128+
# For demonstration, return an empty DataFrame
129+
return pd.DataFrame()
130+
131+
# Register the custom data source with the factory
132+
from fin_ds import DataSourceFactory
133+
DataSourceFactory.register_data_source(MyCustomDataSource)
134+
```
135+
136+
#### Using Your Custom Data Source
137+
138+
Once registered, you can instantiate your custom data source using the `DataSourceFactory` just like built-in sources:
139+
140+
```python
141+
# Create an instance of your custom data source
142+
my_custom_ds = DataSourceFactory("MyCustomDataSource")
143+
144+
# Use it to fetch data
145+
data = my_custom_ds.get_ticker_data("AAPL")
146+
```
147+
148+
### Tips for Custom Data Sources
149+
150+
- **Naming**: The name used to instantiate the data source via `DataSourceFactory` is derived from the class name, omitting "DataSource" suffix if present. Ensure your class names are descriptive and unique.
151+
- **API Keys**: If your data source requires an API key, make sure to include logic in your class to handle this securely. You might use environment variables or configuration files to manage API keys outside your codebase.
152+
- **Error Handling**: Implement robust error handling within your custom data source methods to deal with API limitations, network issues, or data inconsistencies.
153+
154+
By following these guidelines, you can seamlessly integrate custom data sources into your application, enhancing its data retrieval capabilities.
155+
156+
75157
<p align="right">(<a href="#readme-top">back to top</a>)</p>
76158

77159

78160
## Troubleshooting
79161

162+
Encountering issues is a normal part of working with any software package. This section provides guidance on resolving common problems you may face while using this package.
163+
164+
### Data Source Not Found
165+
166+
If you encounter an error indicating that a data source could not be found, consider the following steps:
167+
168+
- **Check the Data Source Name**: Ensure that the name you're using to instantiate the data source matches one of the available data sources. Remember, the name is case-sensitive.
169+
170+
- **List Available Data Sources**: Use `DataSourceFactory.data_sources` to list all registered data sources to verify if your desired data source is available.
171+
172+
- **Custom Data Source Registration**: If you're trying to use a custom data source, ensure it has been registered correctly with `DataSourceFactory.register_data_source()` before attempting to use it.
173+
174+
### ImportError or ModuleNotFoundError
175+
176+
These errors can occur when the package tries to dynamically load a data source module but fails. Possible reasons include:
177+
178+
- **Incorrect Directory Structure**: Verify that your custom data source files are placed in the correct directory if they follow the built-in data source convention.
179+
180+
- **Incorrect Module Name**: Ensure that the module file name matches the expected naming convention (`lowercase` version of the data source class name).
181+
182+
- **Environment Issues**: If you're using a virtual environment, ensure it's activated, and the package is installed within it.
183+
184+
### API Key Errors
185+
186+
If your data source requires an API key and you encounter authentication or access errors:
187+
188+
- **Verify API Key**: Check that the API key is correct and has the necessary permissions.
189+
190+
- **Configuration Check**: Ensure that the API key is properly configured, either through environment variables or configuration files as expected by your data source class.
191+
192+
### Data Fetching Errors
193+
194+
Problems fetching data can arise due to various reasons:
195+
196+
- **Network Issues**: Verify your internet connection.
197+
198+
- **API Limitations**: Some APIs have call rate limits. Ensure you're not exceeding these limits.
199+
200+
- **Incorrect Parameters**: Verify that the parameters passed to the data fetching methods (e.g., ticker symbols) are correct and supported by the data source.
201+
202+
### Debugging Tips
203+
204+
- **Logging**: Increase the logging level to `DEBUG` to get more detailed output that might help identify the issue.
205+
206+
```python
207+
import logging
208+
logging.basicConfig(level=logging.DEBUG)
209+
```
210+
211+
- **Interactive Python Shell**: Experiment with your data sources in an interactive Python shell (e.g., `ipython` or `python` REPL) for quicker feedback and easier troubleshooting.
212+
213+
### Seeking Further Assistance
214+
215+
If you've gone through these steps and still face issues, consider seeking further assistance by:
216+
- **Checking the Documentation**: Review the package documentation for any additional troubleshooting tips or known issues.
217+
- **GitHub Issues**: If you suspect a bug or have a feature request, use the GitHub Issues page for the project to search for existing issues or create a new one.
218+
219+
220+
221+
80222
<p align="right">(<a href="#readme-top">back to top</a>)</p>
81223

82224

83225
## Release history
226+
227+
For a more detailed changelog, including the list of all changes for each version, please refer to the [Releases](https://github.com/mattsmith321/fin-ds/releases) page on GitHub.
228+
84229
* 0.3.0 - Added Nasdaq data sources using [nasdaq-data-link](https://pypi.org/project/Nasdaq-Data-Link/) package.
85230
* 0.3.1 - Fixed how tickers with special characters are handled (at least for BRK-A).
86231
* 1.0.0 - Made changes to class and module names to support dynamic loading.
232+
* 1.1.0 - Added dynamic registration of custom data source classes.
233+
234+
<p align="right">(<a href="#readme-top">back to top</a>)</p>
235+
236+
237+
238+
### 5. Include Contribution Guidelines
239+
240+
```markdown
241+
## Contributing
242+
243+
Contributions are welcome! If you'd like to contribute, please follow these steps:
244+
245+
1. Fork the repository.
246+
2. Create a new branch for your feature or fix.
247+
3. Commit your changes with clear, descriptive messages.
248+
4. Push your branch and submit a pull request.
249+
250+
Please ensure your code adheres to the [Black](https://github.com/psf/black) code style, and include unit tests for new features or fixes. For more details, check out our CONTRIBUTING.md file.
87251

88252
<p align="right">(<a href="#readme-top">back to top</a>)</p>
253+
254+

examples/example.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
from fin_ds.data_source_factory import DataSourceFactory
22

33

4-
data_sources = DataSourceFactory.data_sources
4+
# data_sources = DataSourceFactory.data_sources
55
# data_sources = ["Alpha Vantage", "EODHD", "Nasdaq", "Tiingo", "Yahoo Finance"]
6-
# data_sources = ["Tiingo"]
76

87
tickers = ["AAPL"]
98
# tickers = [
@@ -31,6 +30,14 @@
3130

3231
print(DataSourceFactory.data_sources)
3332

33+
from portfoliovisualizer import PortfolioVisualizerDataSource
34+
35+
data_sources = ["PortfolioVisualizer"]
36+
37+
DataSourceFactory.register_data_source(PortfolioVisualizerDataSource)
38+
39+
print(DataSourceFactory.data_sources)
40+
3441
for data_source in data_sources:
3542
print(f"Fetching data from {data_source}...")
3643
ds = DataSourceFactory(data_source)

fin_ds/data_sources/portfoliovisualizer.py renamed to examples/portfoliovisualizer.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import pandas as pd
55
from pandas.tseries.offsets import MonthEnd
66

7-
from .base_data_source import BaseDataSource
7+
from fin_ds.data_sources.base_data_source import BaseDataSource
88

99
# module-level (or global-level) variables/constants
1010
logger = logging.getLogger(__name__)

0 commit comments

Comments
 (0)