| | |
| | 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) |