Reputation: 25
I am trying to test out few algorithms for trading, however, I am getting the error
AttributeError: 'tuple' object has no attribute 'lower'
I am using YF data here is the code:
import yfinance as yf
import pandas as pd
import numpy as np
import backtrader as bt
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
from xgboost import XGBClassifier
from sklearn.metrics import accuracy_score
import nltk
from nltk.sentiment.vader import SentimentIntensityAnalyzer
from datetime import datetime
from pylab import mpl,plt
# Ensure that nltk's VADER lexicon is downloaded
nltk.download('vader_lexicon')
# 1. Download historical data
ticker = 'AAPL' # Example: Apple stock
start_date = '2010-01-01'
end_date = '2024-01-01'
data = yf.download(ticker, start=start_date, end=end_date)
data.head()
#calculating sma values for two different rolling window sizes
data['SMA_50'] = data['Close'].rolling(window=50).mean()
data['SMA_200'] = data['Close'].rolling(window=200).mean()
plt.figure(figsize=(12, 6))
plt.plot(data['Close'], label='Closing Price', alpha=0.5)
plt.plot(data['SMA_50'], label='shorter sma 50', linewidth=2)
plt.plot(data['SMA_200'], label='larger sma 200', linewidth=2)
plt.legend()
plt.title('AAPL with SMA (50 & 100 Days)')
plt.show()
data['Position']=np.where(data['SMA_50']>data['SMA_200'],1,-1)
data.dropna(inplace=True)
# Create the features and target variable
data['Price_Change'] = data['Close'].shift(-1) - data['Close']
data['Target'] = np.where(data['Price_Change'] > 0, 1, 0) # 1 if price goes up, 0 if price goes down
# Remove NaN values (for backtesting and machine learning)
data = data.dropna()
# Features for machine learning models
features = ['SMA_50', 'SMA_200', 'Returns', 'Sentiment']
# 6. Train-Test Split for ML models
X = data[features]
y = data['Target']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, shuffle=False)
# 7. Machine Learning Models
# Random Forest
rf_model = RandomForestClassifier(n_estimators=100, random_state=42)
rf_model.fit(X_train, y_train)
rf_predictions = rf_model.predict(X_test)
rf_accuracy = accuracy_score(y_test, rf_predictions)
# XGBoost
xgb_model = XGBClassifier(n_estimators=100, random_state=42)
xgb_model.fit(X_train, y_train)
xgb_predictions = xgb_model.predict(X_test)
xgb_accuracy = accuracy_score(y_test, xgb_predictions)
print(f"Random Forest Accuracy: {rf_accuracy}")
print(f"XGBoost Accuracy: {xgb_accuracy}")
# 8. Backtesting Setup: Define Strategy Classes for Backtrader
class SMACrossover(bt.SignalStrategy):
def __init__(self):
self.signal_add(bt.SIGNAL_LONG, data['Position'])
class RandomForestStrategy(bt.SignalStrategy):
def __init__(self):
self.model = rf_model
self.signal_add(bt.SIGNAL_LONG, self.predict_signal)
def predict_signal(self):
latest_data = np.array([data['SMA_50'][-1], data['SMA_200'][-1], data['Returns'][-1], data['Sentiment'][-1]]).reshape(1, -1)
prediction = self.model.predict(latest_data)
return prediction[0]
class XGBoostStrategy(bt.SignalStrategy):
def __init__(self):
self.model = xgb_model
self.signal_add(bt.SIGNAL_LONG, self.predict_signal)
def predict_signal(self):
latest_data = np.array([data['SMA_50'][-1], data['SMA_200'][-1], data['Returns'][-1], data['Sentiment'][-1]]).reshape(1, -1)
prediction = self.model.predict(latest_data)
return prediction[0]
class SentimentStrategy(bt.SignalStrategy):
def __init__(self):
self.signal_add(bt.SIGNAL_LONG, self.predict_signal)
def predict_signal(self):
# Using sentiment directly in the strategy as a buy signal
sentiment = data['Sentiment'][-1]
if sentiment > 0.1: # If sentiment is positive, go long
return 1
else:
return -1 # If sentiment is negative, avoid or sell
# Ensure the index is in datetime format
data.index = pd.to_datetime(data.index)
# Backtesting function
def run_backtest(strategy_class):
cerebro = bt.Cerebro()
cerebro.addstrategy(strategy_class)
# Pass filtered data
data_feed = bt.feeds.PandasData(dataname=data)
cerebro.adddata(data_feed)
cerebro.broker.set_cash(10000)
#cerebro.broker.set_commission(commission=0.001)
cerebro.run()
return cerebro.broker.get_value()
# Run backtests
sma_value = run_backtest(SMACrossover)
rf_value = run_backtest(RandomForestStrategy)
xgb_value = run_backtest(XGBoostStrategy)
sentiment_value = run_backtest(SentimentStrategy)
print(f"SMA Crossover Strategy Final Portfolio Value: {sma_value}")
print(f"Random Forest Strategy Final Portfolio Value: {rf_value}")
print(f"XGBoost Strategy Final Portfolio Value: {xgb_value}")
print(f"Sentiment Strategy Final Portfolio Value: {sentiment_value}")
The error is happening when I am running the backtestest, basically towards the last part of the code, I have tried multiple solutions , they don't seem to be working
sma_value = run_backtest(SMACrossover)
Please help!
Upvotes: 0
Views: 134