| import os |
| import yfinance as yf |
| import pandas as pd |
| from newsapi import NewsApiClient |
| from transformers import pipeline |
| import tensorflow as tf |
| from tensorflow import keras |
| from sklearn.preprocessing import MinMaxScaler |
| import numpy as np |
| from datetime import datetime, timedelta |
| import alpaca_trade_api as tradeapi |
| from langchain_community.llms import HuggingFaceEndpoint |
| import logging |
|
|
| |
| logging.basicConfig(level=logging.INFO) |
| logger = logging.getLogger(__name__) |
|
|
| |
| NEWSAPI_KEY = os.getenv('NEWSAPI_KEY', 'your_newsapi_key') |
| ALPACA_API_KEY = os.getenv('ALPACA_API_KEY', 'your_alpaca_api_key') |
| ALPACA_SECRET_KEY = os.getenv('ALPACA_SECRET_KEY', 'your_alpaca_secret_key') |
| APCA_API_KEY_ID = os.getenv('APCA_API_KEY_ID', ALPACA_API_KEY) |
| APCA_API_SECRET_KEY = os.getenv('APCA_API_SECRET_KEY', ALPACA_SECRET_KEY) |
|
|
| |
| if not all([NEWSAPI_KEY, APCA_API_KEY_ID, APCA_API_SECRET_KEY]): |
| raise ValueError("Ensure all API keys and secret keys are set as environment variables.") |
|
|
| |
| newsapi = NewsApiClient(api_key=NEWSAPI_KEY) |
| |
| HF_TOKEN = os.getenv("HF_TOKEN") |
| llm = HuggingFaceEndpoint( |
| |
| |
| repo_id="mrm8488/distilroberta-finetuned-financial-news-sentiment-analysis", |
| |
| |
| task="financial-analysis", |
| max_new_tokens=512, |
| top_k=5, |
| temperature=0.2, |
| repetition_penalty=1.03, |
| timeout=300, |
| huggingfacehub_api_token=HF_TOKEN |
| ) |
| |
| alpaca_api = tradeapi.REST(APCA_API_KEY_ID, APCA_API_SECRET_KEY, base_url='https://paper-api.alpaca.markets') |
|
|
| def collect_market_data(ticker): |
| data = yf.download(ticker, start=(datetime.now() - timedelta(days=365)).strftime('%Y-%m-%d'), end=datetime.now().strftime('%Y-%m-%d')) |
| data.to_csv(f'{ticker}_market_data.csv') |
| logger.info(f'Market data for {ticker} collected successfully.') |
|
|
| def collect_news_data(query, from_date, to_date): |
| all_articles = newsapi.get_everything(q=query, from_param=from_date, to=to_date, language='en', sort_by='relevancy') |
| if all_articles['status'] == 'ok': |
| articles_df = pd.DataFrame(all_articles['articles']) |
| articles_df.to_csv('news_data.csv') |
| logger.info(f'News data for {query} collected successfully.') |
| else: |
| logger.error(f'Error collecting news data: {all_articles["message"]}') |
|
|
| def perform_sentiment_analysis(): |
| sentiment_pipeline = pipeline("sentiment-analysis") |
| try: |
| news_data = pd.read_csv('news_data.csv') |
| news_data['sentiment'] = news_data['description'].apply(lambda x: sentiment_pipeline(x)[0]['label'] if pd.notna(x) else 'NEUTRAL') |
| news_data.to_csv('sentiment_data.csv', index=False) |
| logger.info('Sentiment analysis performed successfully.') |
| except Exception as e: |
| logger.error(f'Error performing sentiment analysis: {e}') |
|
|
| def train_price_prediction_model(ticker): |
| data = pd.read_csv(f'{ticker}_market_data.csv') |
| data = data[['Date', 'Close']].set_index('Date') |
| scaler = MinMaxScaler(feature_range=(0, 1)) |
| scaled_data = scaler.fit_transform(data) |
|
|
| X = [] |
| y = [] |
|
|
| for i in range(60, len(scaled_data)): |
| X.append(scaled_data[i-60:i, 0]) |
| y.append(scaled_data[i, 0]) |
|
|
| X = np.array(X) |
| y = np.array(y) |
| X = np.reshape(X, (X.shape[0], X.shape[1], 1)) |
|
|
| model = keras.Sequential([ |
| keras.layers.LSTM(50, return_sequences=True, input_shape=(X.shape[1], 1)), |
| keras.layers.LSTM(50, return_sequences=False), |
| keras.layers.Dense(25), |
| keras.layers.Dense(1) |
| ]) |
|
|
| model.compile(optimizer='adam', loss='mean_squared_error') |
| model.fit(X, y, batch_size=1, epochs=1) |
|
|
| model.save(f'{ticker}_price_prediction_model.h5') |
| logger.info('Price prediction model trained successfully.') |
|
|
| def make_trade_decision(ticker): |
| model = keras.models.load_model(f'{ticker}_price_prediction_model.h5') |
| data = pd.read_csv(f'{ticker}_market_data.csv') |
| last_60_days = data['Close'].tail(60).values |
| last_60_days_scaled = MinMaxScaler(feature_range=(0, 1)).fit_transform(last_60_days.reshape(-1, 1)) |
|
|
| X_test = [] |
| X_test.append(last_60_days_scaled) |
| X_test = np.array(X_test) |
| X_test = np.reshape(X_test, (X_test.shape[0], X_test.shape[1], 1)) |
|
|
| predicted_price = model.predict(X_test) |
| predicted_price = MinMaxScaler(feature_range=(0, 1)).inverse_transform(predicted_price) |
|
|
| current_price = yf.download(ticker, period='1d')['Close'].values[0] |
|
|
| if predicted_price > current_price: |
| alpaca_api.submit_order( |
| symbol=ticker, |
| qty=1, |
| side='buy', |
| type='market', |
| time_in_force='gtc' |
| ) |
| logger.info(f'Bought 1 share of {ticker}') |
| else: |
| alpaca_api.submit_order( |
| symbol=ticker, |
| qty=1, |
| side='sell', |
| type='market', |
| time_in_force='gtc' |
| ) |
| logger.info(f'Sold 1 share of {ticker}') |
|
|
| if __name__ == "__main__": |
| TICKER = 'AAPL' |
| QUERY = 'Apple Inc' |
| FROM_DATE = (datetime.now() - timedelta(days=30)).strftime('%Y-%m-%d') |
| TO_DATE = datetime.now().strftime('%Y-%m-%d') |
|
|
| collect_market_data(TICKER) |
| collect_news_data(QUERY, FROM_DATE, TO_DATE) |
| perform_sentiment_analysis() |
| train_price_prediction_model(TICKER) |
| make_trade_decision(TICKER) |
|
|