Saturday, February 15, 2025

Enhancing Algorithmic Trading with Neuro-Symbolic AI: A Hybrid Approach for Smarter Market Predictions

 



Introduction to Neuro-Symbolic AI

Neuro-Symbolic AI is an advanced paradigm that combines neural networks (deep learning) with symbolic reasoning to enhance decision-making, interpretability, and generalization. While neural models excel at pattern recognition from unstructured data, symbolic AI uses logic-based rules to perform reasoning and inference. The integration of these two approaches results in more robust, explainable, and data-efficient AI systems.

Use of Neuro-Symbolic AI in Algorithmic Trading

In algorithmic trading, Neuro-Symbolic AI plays a crucial role in improving market predictions and trade execution by:

  • Combining deep learning (e.g., Transformer-based forecasting) with symbolic reasoning (e.g., sentiment analysis, volatility rules).
  • Adjusting price forecasts dynamically based on real-time sentiment analysis of news articles.
  • Using logic-driven volatility factors to refine predictions and mitigate market noise.
  • Enhancing risk management by integrating rule-based adjustments to model-driven outputs.


Summary of the Code

The provided code implements an algorithmic trading model enhanced with Neuro-Symbolic AI techniques:

  1. Sentiment Analysis Using Llama3.1: Extracts sentiment scores for two stocks based on local news data.
  2. Stock Data Generation: Simulates stock prices using a Multivariate Gaussian distribution.
  3. i-Transformer Model for Forecasting: A deep learning model based on a Transformer encoder predicts future stock prices using a sliding window of past prices.
  4. Neuro-Symbolic Adjustment: Adjusts the model’s predictions using sentiment scores and a volatility factor.
  5. Simulated Trading Decisions: Iterates through test data, predicting stock prices and applying symbolic adjustments to improve trading decisions.

This hybrid approach enhances algorithmic trading by incorporating both data-driven (neural) and logic-driven (symbolic) methodologies, leading to more accurate and interpretable market predictions.

Code: Algorithmic Trading using Neuro-Symbolic AI (a toy example):

 import numpy as np

import pandas as pd
import tensorflow as tf
import re
# from tensorflow import keras
from keras.models import Model
from keras.layers import Input, Dense, Dropout, MultiHeadAttention, LayerNormalization, \
GlobalAveragePooling1D, Conv1D, Add
import json
import requests
from groq import Groq

client = Groq(
api_key='PLEASE USE YOUR OWN API KEY',
)
stock1 = "Stock_A"
stock2 = "Stock_B"
# Step 1: Fetch News from Local Storage and Use Llama 3.1 for Sentiment Analysis
def fetch_news_from_local(stock_name):
with open(stock_name, 'r') as file:
news_data = json.load(file)
return news_data # Assume the JSON file contains text news data
context1 = str(fetch_news_from_local("news_data_Stock_A.json")) + ":\n"
question1 = "calculate the sentiment score in the range [-1.0 to +1.0] for " + stock1 +"return only number nothing else"
context2 = str(fetch_news_from_local("news_data_Stock_B.json")) + ":\n"
question2 = "calculate the sentiment score in the range [-1.0 to +1.0] for " + stock2 +"return only number nothing else"
# Combine context and question
input_prompt1 = f"{context1}\nQuestion: {question1}\nAnswer:"
input_prompt2 = f"{context2}\nQuestion: {question2}\nAnswer:"
# Step 2: Calculate the sentiment
def extract_sentiment_score(input_prompt):
chat_completion = client.chat.completions.create(
messages=[
{
"role": "user",
"content": input_prompt,
}
],
model="llama-3.1-8b-instant",
# model="llama-3.1-70b-versatile",
# model = "llama3-70b-8192"
)
response = chat_completion.choices[0].message.content

# Use regex to extract the first numerical value from the response
match = re.search(r'[-+]?\d*\.\d+|\d+', response) # Extracts numbers including negatives & decimals
if match:
return float(match.group()) # Convert extracted number to float
else:
raise ValueError(f"Could not extract a valid sentiment score from response: {response}")

llm_output1 = extract_sentiment_score(input_prompt1)
# llm_output1 = float(llm_output1)
print(llm_output1)
llm_output2 = extract_sentiment_score(input_prompt2)
# llm_output2 = float(llm_output2)
print(llm_output2)

# Step 3: Generate Synthetic Stock Data (Multivariate Gaussian)
def generate_stock_data(days=180, mean=[100, 200], cov=[[1, 0.5], [0.5, 1]]):
np.random.seed(42)
stock_data = np.random.multivariate_normal(mean, cov, size=days)
df = pd.DataFrame(stock_data, columns=['Stock_A', 'Stock_B'])
df['Date'] = pd.date_range(start='2024-01-01', periods=days, freq='D')
return df

stock_df = generate_stock_data()

# Step 4: Prepare Data for i-Transformer
def prepare_data(df, window=10):
data = df[['Stock_A', 'Stock_B']].values
X, y = [], []
for i in range(len(data) - window):
X.append(data[i:i + window])
y.append(data[i + window])
return np.array(X), np.array(y)


X, y = prepare_data(stock_df)
train_size = int(0.8 * len(X))
X_train, X_test, y_train, y_test = X[:train_size], X[train_size:], y[:train_size], y[train_size:]

print("X_train => ",X_train)
print("X_test => ",X_test)

def i_transformer_encoder(inputs, head_size=64, num_heads=4, ff_dim=128, dropout=0.1):
# Apply Conv1D layer to adjust the shape
x = Conv1D(filters=head_size, kernel_size=1, activation='relu')(inputs)

# Apply MultiHeadAttention
attn_output = MultiHeadAttention(key_dim=head_size, num_heads=num_heads)(x, x)
attn_output = Dropout(dropout)(attn_output)
attn_output = LayerNormalization(epsilon=1e-6)(attn_output)

# Ensure that attention output has the same shape as 'x' before addition
attn_output = Dense(head_size)(attn_output)

# Residual connection
res = Add()([x, attn_output])

# Feed-forward layers
x = Dense(ff_dim, activation="relu")(res)
x = Dropout(dropout)(x)
x = Dense(head_size)(x)
x = LayerNormalization(epsilon=1e-6)(x)

return Add()([x, res])

input_shape = (X.shape[1], X.shape[2])
inputs = Input(shape=input_shape)
x = i_transformer_encoder(inputs)
x = GlobalAveragePooling1D()(x)
x = Dense(2)(x)

model = Model(inputs, x)
model.compile(optimizer='adam', loss='mse')
model.fit(X_train, y_train, epochs=20, batch_size=16, validation_data=(X_test, y_test))

# Step 6: Advanced Neuro-Symbolic AI Adjustment (Updated)
def neuro_symbolic_adjustment(forecast, input_prompt):
# Analyze sentiment for both stocks
sentiment_1 = extract_sentiment_score(input_prompt)
# Compute volatility factors for both stocks
volatility_factor_1 = np.std([np.random.uniform(-0.05, 0.05) for _ in range(10)]) # Simulated volatility for Stock 1

symbolic_adjustment = sentiment_1 * 0.05 + volatility_factor_1 # Adjust forecast with both factors

# Adjust forecast values
adjusted_forecast = forecast * (1 + symbolic_adjustment)
return max(0, adjusted_forecast) # Ensure price does not go negative

# Step 7: Simulate Trading Decisions
import csv

# Step 7: Simulate Trading Decisions & Save to CSV
results = []

for i in range(len(y_test)):
forecast = model.predict(X_test[i:i + 1])[0]

# Raw Predictions
raw_forecast_A = forecast[0]
raw_forecast_B = forecast[1]

# Adjusted Predictions using Neuro-Symbolic AI
adjusted_forecast_A = neuro_symbolic_adjustment(raw_forecast_A, input_prompt1)
adjusted_forecast_B = neuro_symbolic_adjustment(raw_forecast_B, input_prompt2)

# Calculate the percentage change due to neuro-symbolic AI
change_A = ((adjusted_forecast_A - raw_forecast_A) / raw_forecast_A) * 100
change_B = ((adjusted_forecast_B - raw_forecast_B) / raw_forecast_B) * 100

# Print results
print(f"Day {i + 1}: Stock_A Raw: {raw_forecast_A:.2f}, Adjusted: {adjusted_forecast_A:.2f}{change_A:.2f}%)")
print(f" Stock_B Raw: {raw_forecast_B:.2f}, Adjusted: {adjusted_forecast_B:.2f}{change_B:.2f}%)")

# Append results to list for saving
results.append([i + 1, raw_forecast_A, adjusted_forecast_A, change_A, raw_forecast_B, adjusted_forecast_B, change_B])

# Save results to CSV
csv_filename = "trading_predictions.csv"
with open(csv_filename, mode="w", newline="") as file:
writer = csv.writer(file)
writer.writerow(["Day", "Stock_A_Raw", "Stock_A_Adjusted", "Stock_A_Change(%)",
"Stock_B_Raw", "Stock_B_Adjusted", "Stock_B_Change(%)"])
writer.writerows(results)

print(f"\nPredictions saved to {csv_filename}")


Code: Dummy News Data Generator.

import json


def generate_dummy_news(stock_name):
"""
Generates dummy news data for a given stock and saves it as a JSON file.
:param stock_name: Name of the stock for which dummy news data is generated.
"""
news_samples = {
"Stock_A": [
"Stock_A sees a surge in trading volume due to positive earnings report.",
"Analysts predict continued growth for Stock_A in the coming quarter.",
"Stock_A's new product launch receives strong market approval."
],
"Stock_B": [
"Stock_B faces regulatory scrutiny leading to a drop in stock value.",
"Market experts suggest caution as Stock_B struggles with supply chain issues.",
"Stock_B's latest acquisition expected to boost long-term profits."
]
}

with open(f'news_data_{stock_name}.json', 'w') as file:
json.dump(news_samples.get(stock_name, []), file, indent=4)
print(f"Dummy news data for {stock_name} saved.")


# Generate dummy news for Stock_A and Stock_B
generate_dummy_news("Stock_A")
generate_dummy_news("Stock_B")

Reference:

  1. Besold, T. R., et al. (2017). Neural-Symbolic Learning and Reasoning: A Survey and Interpretation.
  2. Garcez, A. S., & Lamb, L. C. (2020). Neurosymbolic AI: The 3rd Wave.
  3. Bengio, Y., et al. (2021). The Neuro-Symbolic Concept Learner.
  4. Mitchell, M. (2019). Artificial Intelligence: A Guide to Intelligent Systems.

3 comments:

  1. This is an excellent article that demonstrates how Neuro-Symbolic AI can enhance algorithmic trading by combining the predictive power of deep learning with the interpretability of symbolic reasoning. The integration of sentiment analysis, Transformer-based forecasting, and rule-driven adjustments provides a practical example of building intelligent trading systems that are both data-driven and explainable. The detailed implementation makes the concepts easier to understand and apply in real-world financial analytics scenarios.

    ReplyDelete
  2. The article highlights how advanced forecasting models can be combined with market sentiment and volatility analysis to improve stock price prediction and trading decisions. These concepts are closely related to Time Series Projects, where sequential data analysis, trend forecasting, and predictive modeling techniques are used to support intelligent decision-making in financial and business applications.

    ReplyDelete
  3. Since the proposed solution relies on Transformer-based neural architectures for learning patterns from historical market data, the topic also aligns closely with Deep Learning Projects for Final Year. These projects focus on leveraging advanced neural network models to capture complex temporal relationships, improve forecasting accuracy, and support intelligent predictive analytics systems.

    ReplyDelete