Skip to content

Commit

Permalink
Add mutual funds trades tracking (#16)
Browse files Browse the repository at this point in the history
Related to #8

Add real-time mutual funds trades tracking functionality.

* **New File: `data/mutual_funds_tracker.py`**
- Define `MutualFundsTracker` class to handle real-time tracking of
mutual funds trades.
- Implement `fetch_mutual_funds_trades` method to fetch real-time mutual
funds trades data.
- Implement `process_mutual_funds_trades` method to process mutual funds
trades data.

* **Update `main.py`**
  - Import `MutualFundsTracker` from `data/mutual_funds_tracker`.
  - Initialize `MutualFundsTracker` in the main function.
- Add `mutual_funds_tracker` to the `process_market_data` function
parameters.
- Create a task to process mutual funds trades in `process_market_data`
function.

* **Update `config/config.py`**
- Add `mutual_funds_tracking_enabled` and `mutual_funds_data_source`
settings under `investment_banking` section.

* **Update `config/api_config.py`**
  - Add `mutual_funds_api_key` and `mutual_funds_api_endpoint` settings.
- Add `mutual_funds_headers` method to return headers for Mutual Funds
API.
- Add `get_mutual_funds_endpoint` method to return the Mutual Funds API
endpoint.

* **New File: `tests/test_mutual_funds_tracker.py`**
  - Define tests for `MutualFundsTracker` class.
  - Test `fetch_mutual_funds_trades` method.
  - Test `process_mutual_funds_trades` method.
  • Loading branch information
vishwamartur authored Nov 25, 2024
2 parents 1763904 + b920e96 commit 678d6d3
Show file tree
Hide file tree
Showing 5 changed files with 137 additions and 4 deletions.
19 changes: 19 additions & 0 deletions config/api_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ def __init__(self):
self.news_api_key = os.getenv("NEWS_API_KEY")
self.news_api_endpoint = os.getenv("NEWS_API_ENDPOINT")

# Mutual Funds API configurations
self.mutual_funds_api_key = os.getenv("MUTUAL_FUNDS_API_KEY")
self.mutual_funds_api_endpoint = os.getenv("MUTUAL_FUNDS_API_ENDPOINT")

# Additional API configurations can be added here
# Example for other market data or sentiment analysis APIs:
# self.other_api_key = os.getenv("OTHER_API_KEY")
Expand Down Expand Up @@ -71,6 +75,15 @@ def news_headers(self):
"Content-Type": "application/json",
}

def mutual_funds_headers(self):
"""
Returns headers required for making requests to the Mutual Funds API.
"""
return {
"Authorization": f"Bearer {self.mutual_funds_api_key}",
"Content-Type": "application/json",
}

def get_dhan_endpoint(self, path):
"""
Constructs and returns a full Dhan API endpoint for a given path.
Expand All @@ -94,3 +107,9 @@ def get_news_endpoint(self):
Returns the News API endpoint.
"""
return self.news_api_endpoint

def get_mutual_funds_endpoint(self):
"""
Returns the Mutual Funds API endpoint.
"""
return self.mutual_funds_api_endpoint
2 changes: 2 additions & 0 deletions config/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ def load_config():
"investment_banking": {
"tracking_enabled": os.getenv("INVESTMENT_BANKING_TRACKING_ENABLED", "false") == "true",
"data_source": os.getenv("INVESTMENT_BANKING_DATA_SOURCE", "default_source"),
"mutual_funds_tracking_enabled": os.getenv("MUTUAL_FUNDS_TRACKING_ENABLED", "false") == "true",
"mutual_funds_data_source": os.getenv("MUTUAL_FUNDS_DATA_SOURCE", "default_source"),
},
"logging": {
"log_level": os.getenv("LOG_LEVEL", "INFO"),
Expand Down
56 changes: 56 additions & 0 deletions data/mutual_funds_tracker.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import logging
from typing import Dict, Any
from datetime import datetime

class MutualFundsTracker:
"""
Handles real-time tracking of mutual funds trades.
"""

def __init__(self, config: Dict[str, Any]):
"""
Initialize the MutualFundsTracker with configuration settings.
Args:
config: Dictionary containing configuration parameters
"""
self.config = config
self.logger = logging.getLogger(__name__)
self.logger.info("Initializing MutualFundsTracker")

async def fetch_mutual_funds_trades(self) -> Dict[str, Any]:
"""
Fetch real-time mutual funds trades data.
Returns:
Dictionary containing mutual funds trades data
"""
try:
self.logger.info("Fetching mutual funds trades data")
# Implementation for fetching mutual funds trades data would go here
# This would typically involve API calls to the data provider

# Placeholder return
return {
"timestamp": datetime.now().isoformat(),
"trades": []
}

except Exception as e:
self.logger.error(f"Error fetching mutual funds trades data: {str(e)}")
raise

async def process_mutual_funds_trades(self, trades_data: Dict[str, Any]) -> None:
"""
Process mutual funds trades data.
Args:
trades_data: Dictionary containing mutual funds trades data
"""
try:
self.logger.info("Processing mutual funds trades data")
# Implementation for processing mutual funds trades data would go here

except Exception as e:
self.logger.error(f"Error processing mutual funds trades data: {str(e)}")
raise
13 changes: 9 additions & 4 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
from telegram.ext import Updater, CommandHandler, MessageHandler, Filters
from data.weather_data_fetcher import WeatherDataFetcher
from data.news_data_fetcher import NewsDataFetcher
from data.mutual_funds_tracker import MutualFundsTracker

# Load environment variables and validate required keys
load_dotenv()
Expand Down Expand Up @@ -59,7 +60,8 @@ async def process_market_data(
notifier: Notifier,
investment_banking_tracker: InvestmentBankingTracker,
weather_fetcher: WeatherDataFetcher,
news_fetcher: NewsDataFetcher
news_fetcher: NewsDataFetcher,
mutual_funds_tracker: MutualFundsTracker
) -> None:
"""
Process incoming market data asynchronously and execute trading strategies
Expand All @@ -75,9 +77,10 @@ async def process_market_data(
investment_banking_task = asyncio.create_task(investment_banking_tracker.process_investment_banking_trades(data))
weather_task = asyncio.create_task(weather_fetcher.fetch_and_process_weather_data("New York"))
news_task = asyncio.create_task(news_fetcher.fetch_news_data("market"))
mutual_funds_task = asyncio.create_task(mutual_funds_tracker.process_mutual_funds_trades(data))

futures_signal, options_signal, sentiment, _, weather_data, news_data = await asyncio.gather(
futures_task, options_task, sentiment_task, investment_banking_task, weather_task, news_task
futures_signal, options_signal, sentiment, _, weather_data, news_data, _ = await asyncio.gather(
futures_task, options_task, sentiment_task, investment_banking_task, weather_task, news_task, mutual_funds_task
)

# Handle futures signals
Expand Down Expand Up @@ -154,6 +157,7 @@ async def main():
api_key=config["api"]["news_api_key"],
api_endpoint=config["api"]["news_api_endpoint"]
)
mutual_funds_tracker = MutualFundsTracker(config["investment_banking"])

# Run backtesting with performance metrics
backtester = Backtester()
Expand All @@ -176,7 +180,8 @@ async def on_message(data: Dict) -> None:
notifier,
investment_banking_tracker,
weather_fetcher,
news_fetcher
news_fetcher,
mutual_funds_tracker
)

# Start WebSocket connection
Expand Down
51 changes: 51 additions & 0 deletions tests/test_mutual_funds_tracker.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import unittest
from unittest.mock import patch, AsyncMock
from data.mutual_funds_tracker import MutualFundsTracker

class TestMutualFundsTracker(unittest.TestCase):
def setUp(self):
self.config = {
"investment_banking": {
"mutual_funds_tracking_enabled": True,
"mutual_funds_data_source": "test_source"
}
}
self.tracker = MutualFundsTracker(self.config)

@patch('data.mutual_funds_tracker.MutualFundsTracker.fetch_mutual_funds_trades')
async def test_fetch_mutual_funds_trades(self, mock_fetch):
# Mock response data
mock_data = {
"timestamp": "2023-01-01T00:00:00Z",
"trades": [
{"trade_id": 1, "symbol": "TEST", "price": 100.0, "volume": 1000}
]
}
mock_fetch.return_value = mock_data

# Test fetching data
result = await self.tracker.fetch_mutual_funds_trades()

# Verify results
self.assertEqual(result["timestamp"], "2023-01-01T00:00:00Z")
self.assertEqual(len(result["trades"]), 1)
self.assertEqual(result["trades"][0]["symbol"], "TEST")

@patch('data.mutual_funds_tracker.MutualFundsTracker.process_mutual_funds_trades')
async def test_process_mutual_funds_trades(self, mock_process):
# Mock trades data
trades_data = {
"timestamp": "2023-01-01T00:00:00Z",
"trades": [
{"trade_id": 1, "symbol": "TEST", "price": 100.0, "volume": 1000}
]
}

# Test processing data
await self.tracker.process_mutual_funds_trades(trades_data)

# Verify processing was called
mock_process.assert_called_once_with(trades_data)

if __name__ == '__main__':
unittest.main()

0 comments on commit 678d6d3

Please sign in to comment.