|
|
|
import gradio as gr |
|
from datetime import datetime, timedelta |
|
from stocks import AnalysisPipeline, BacktraderIntegration |
|
import matplotlib.pyplot as plt |
|
import matplotlib.dates as mdates |
|
|
|
class GradioInterface: |
|
def __init__(self, pipeline): |
|
self.pipeline = pipeline |
|
self.strategy_params = { |
|
'rsi_period': 14, |
|
'rsi_upper': 70, |
|
'rsi_lower': 30, |
|
'sma_short': 50, |
|
'sma_long': 200, |
|
'max_loss_percent': 5, |
|
'take_profit_percent': 5, |
|
'position_size': 10, |
|
'atr_period': 7, |
|
'atr_multiplier': 3, |
|
'confidence_threshold': 35, |
|
'sentiment_threshold': 25 |
|
} |
|
|
|
def create_settings_interface(self): |
|
with gr.Blocks() as settings_interface: |
|
with gr.Row(): |
|
with gr.Column(): |
|
gr.Markdown("### Parameters for Trading Strategy") |
|
inputs = {} |
|
inputs['rsi_period'] = gr.Number(value=14, label="RSI Period", minimum=1) |
|
inputs['rsi_upper'] = gr.Number(value=70, label="RSI Upper Limit", minimum=0, maximum=100) |
|
inputs['rsi_lower'] = gr.Number(value=30, label="RSI Lower Limit", minimum=0, maximum=100) |
|
inputs['sma_short'] = gr.Number(value=50, label="SMA Short (period)") |
|
inputs['sma_long'] = gr.Number(value=200, label="SMA Long (period)") |
|
inputs['max_loss_percent'] = gr.Slider(1, 100, value=5, step=5, label="Stop Loss (%)") |
|
inputs['take_profit_percent'] = gr.Slider(1, 100, value=5, step=5, label="Take Profit (%)") |
|
inputs['position_size'] = gr.Slider(1, 100, value=5, step=5, label="Position Size(%)") |
|
inputs['atr_period'] = gr.Number(value=14, label="ATR Period") |
|
inputs['atr_multiplier'] = gr.Number(value=3, label="ATR Multiplier") |
|
inputs['confidence_threshold'] = gr.Slider(1, 100, value=30, step=5, label="Confidence Threshold(%)") |
|
inputs['sentiment_threshold'] = gr.Slider(1, 100, value=25, step=5, label="Sentiment Threshold(%)") |
|
save_btn = gr.Button("Save Configuration") |
|
|
|
gr.Markdown(""" |
|
## 📊 Explanation of Trading Strategy Parameters |
|
These parameters configure technical indicators to assist in buy and sell decisions for assets. |
|
### **📉 RSI (Relative Strength Index)** |
|
- **`rsi_period` (14)** → Number of periods to calculate the RSI. |
|
- **`rsi_upper` (70)** → Overbought conditions (sell signal). |
|
- **`rsi_lower` (30)** → Oversold conditions (buy signal). |
|
### **📈 Simple Moving Averages (SMA)** |
|
- **`sma_short` (50)** → Short-term moving average. |
|
- **`sma_long` (200)** → Long-term moving average. |
|
### **📉 Risk Management** |
|
- **`max_loss_percent` (0.02)** → Stop Loss (loss limit). |
|
- **`take_profit_percent` (0.05)** → Take Profit (profit limit). |
|
- **`position_size` (0.1)** → Proportion of total capital to be used in a trade. |
|
### **📊 ATR (Average True Range) - Volatility** |
|
- **`atr_period` (14)** → Number of periods to calculate the ATR. |
|
- **`atr_multiplier` (3)** → ATR multiplier for dynamic stop loss. |
|
""") |
|
|
|
save_btn.click( |
|
self.save_settings, |
|
inputs=[v for v in inputs.values()], |
|
outputs=None |
|
) |
|
return settings_interface |
|
|
|
def save_settings(self, *args): |
|
params = [ |
|
'rsi_period', 'rsi_upper', 'rsi_lower', |
|
'sma_short', 'sma_long', 'max_loss_percent', |
|
'take_profit_percent', 'position_size', |
|
'atr_period', 'atr_multiplier', 'confidence_threshold', 'sentiment_threshold' |
|
] |
|
self.strategy_params = dict(zip(params, args)) |
|
print("Updated parameters:", self.strategy_params) |
|
return gr.Info("Settings saved!") |
|
|
|
def create_main_interface(self): |
|
with gr.Blocks() as main_interface: |
|
with gr.Row(): |
|
with gr.Column(): |
|
ticker_input = gr.Text(label="Ticker (ex: VALE)", placeholder="Insert a stock ticker based on Yahoo Finance") |
|
fetch_new = gr.Dropdown([True, False], label="Check last news information online (Requires API)?", value=False) |
|
api_key_input = gr.Textbox(label="API Key", placeholder="Insert your API Key https://newsapi.org/") |
|
initial_investment = gr.Number(10000, label="Initial Investment (USD)") |
|
years_back = gr.Number(5, label="Historical Data (years back)") |
|
commission = gr.Number(2, label="Trade Commission (%)", minimum=0, maximum=100) |
|
run_btn = gr.Button("Execute Analysis") |
|
with gr.Column(): |
|
plot_output = gr.Plot() |
|
with gr.Row(): |
|
output_md = gr.Markdown() |
|
with gr.Row(): |
|
output_ops = gr.Markdown() |
|
|
|
run_btn.click( |
|
self.run_full_analysis, |
|
inputs=[ticker_input, fetch_new, initial_investment, years_back, commission, api_key_input], |
|
outputs=[output_md, output_ops, plot_output] |
|
) |
|
return main_interface |
|
|
|
def run_full_analysis(self, ticker, fetch_new, initial_investment, years_back, commission, api_key): |
|
|
|
self.pipeline.set_sentiment_threshold(float(self.strategy_params['sentiment_threshold']) / 100) |
|
self.pipeline.set_confidence_threshold(float(self.strategy_params['confidence_threshold']) / 100) |
|
|
|
|
|
result = self.pipeline.analyze_company( |
|
ticker=ticker, |
|
news_api_key=api_key, |
|
fetch_new=fetch_new |
|
) |
|
|
|
if not result: |
|
return "Something went wrong. Please check your inputs.", None, None |
|
|
|
|
|
end_date = datetime.now() |
|
start_date = end_date - timedelta(days=int(years_back * 365)) |
|
|
|
|
|
custom_strategy_params = { |
|
'rsi_period': int(self.strategy_params['rsi_period']), |
|
'rsi_upper': int(self.strategy_params['rsi_upper']), |
|
'rsi_lower': int(self.strategy_params['rsi_lower']), |
|
'sma_short': int(self.strategy_params['sma_short']), |
|
'sma_long': int(self.strategy_params['sma_long']), |
|
'max_loss_percent': float(self.strategy_params['max_loss_percent'])/100, |
|
'take_profit_percent': float(self.strategy_params['take_profit_percent'])/100, |
|
'position_size': float(self.strategy_params['position_size'])/100, |
|
'atr_period': int(self.strategy_params['atr_period']), |
|
'atr_multiplier': int(self.strategy_params['atr_multiplier']), |
|
'confidence_threshold': float(self.strategy_params['confidence_threshold'])/100, |
|
'sentiment_threshold': float(self.strategy_params['sentiment_threshold'])/100 |
|
} |
|
|
|
|
|
bt_integration = BacktraderIntegration(analysis_result=result, strategy_params=custom_strategy_params) |
|
bt_integration.add_data_feed(ticker, start_date, end_date) |
|
final_value, operation_logs = bt_integration.run_simulation( |
|
initial_cash=initial_investment, |
|
commission=commission |
|
) |
|
|
|
|
|
formatted_logs = [] |
|
for log in operation_logs: |
|
if "BUY EXECUTED" in log: |
|
parts = log.split(", ") |
|
date = parts[0].strip() |
|
details = ", ".join(parts[1:]).replace("BUY EXECUTED, ", "") |
|
formatted_logs.append(f"- 🟢 **Buy** ({date}): {details}") |
|
elif "SELL EXECUTED" in log: |
|
parts = log.split(", ") |
|
date = parts[0].strip() |
|
details = ", ".join(parts[1:]).replace("SELL EXECUTED, ", "") |
|
formatted_logs.append(f"- 🔴 **Sell** ({date}): {details}") |
|
elif "TRADE PROFIT" in log: |
|
parts = log.split(", ") |
|
date = parts[0].strip() |
|
details = ", ".join(parts[1:]) |
|
formatted_logs.append(f"- 📈 **Result** ({date}): {details}") |
|
|
|
|
|
output_ops = "### Log :\n\n" + "\n".join(formatted_logs) |
|
|
|
|
|
sentiment = result['sentiment'] |
|
output = f""" |
|
## Recommendation: {result['recommendation']} |
|
|
|
**Confidence**: {result['confidence']['total_confidence']:.2%} |
|
|
|
## Simulation Results: |
|
- **Initial Investment**: ${initial_investment:.2f} |
|
- **Simulation Summary**: {(final_value / initial_investment - 1) * 100:.2f}% |
|
- **Final Portfolio Value**: ${final_value:.2f} |
|
|
|
### Details: |
|
|
|
- **Negative Sentiment**: {sentiment.get('negative', 0.0):.2%} |
|
- **Neutral Sentiment**: {sentiment.get('neutral', 0.0):.2%} |
|
- **Positive Sentiment**: {sentiment.get('positive', 0.0):.2%} |
|
|
|
- **RSI**: {result['technical']['rsi']:.1f} |
|
- **Price vs SMA50**: {result['technical']['price_vs_sma']:.2%} |
|
- **P/E Ratio**: {result['fundamental'].get('trailingPE', 'N/A')} |
|
""" |
|
|
|
|
|
plot = self.generate_simple_plot(bt_integration) |
|
|
|
return output, output_ops, plot |
|
|
|
def generate_simple_plot(self, bt_integration): |
|
plt.figure(figsize=(12, 6)) |
|
datafeed = bt_integration.cerebro.datas[0] |
|
dates = [datetime.fromordinal(int(date)) for date in datafeed.datetime.array] |
|
closes = datafeed.close.array |
|
plt.plot(dates, closes, label='Close Price', linewidth=1.5) |
|
plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m')) |
|
plt.gca().xaxis.set_major_locator(mdates.MonthLocator(interval=3)) |
|
plt.gcf().autofmt_xdate() |
|
plt.title("Historical Price Data") |
|
plt.xlabel("Date") |
|
plt.ylabel("Price (USD)") |
|
plt.legend() |
|
plt.grid(True, alpha=0.3) |
|
return plt.gcf() |
|
|
|
|
|
pipeline = AnalysisPipeline() |
|
interface = GradioInterface(pipeline) |
|
|
|
demo = gr.TabbedInterface( |
|
[interface.create_main_interface(), interface.create_settings_interface()], |
|
["Main Analysis", "Strategy Settings"], |
|
title="Stock Analyst Pro" |
|
) |
|
|
|
if __name__ == "__main__": |
|
demo.launch(share=True) |