File size: 6,481 Bytes
3898efa
 
 
e1d4db9
3898efa
 
e1d4db9
7f41c98
e1d4db9
 
7f41c98
 
3898efa
e1d4db9
 
3898efa
 
e1d4db9
3898efa
e1d4db9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3898efa
 
e1d4db9
3898efa
e1d4db9
 
 
 
 
 
 
 
 
3898efa
e1d4db9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3898efa
 
e1d4db9
3898efa
e1d4db9
3898efa
 
 
e1d4db9
3898efa
 
e1d4db9
 
 
 
 
 
3898efa
e1d4db9
 
 
 
3898efa
 
e1d4db9
 
 
 
 
 
 
 
 
 
3898efa
 
 
 
 
e1d4db9
3898efa
 
e1d4db9
3898efa
 
e1d4db9
 
 
 
3898efa
e1d4db9
3898efa
e1d4db9
 
 
 
 
 
 
 
 
3898efa
e1d4db9
 
 
 
 
 
3898efa
e1d4db9
 
 
3898efa
e1d4db9
 
3898efa
7f41c98
 
 
3898efa
e1d4db9
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
app.py - Enhanced Crypto & Stock Predictor with intuitive UI/UX
"""

import ccxt
import yfinance as yf
import pandas as pd
import numpy as np
import plotly.graph_objects as go
from plotly.subplots import make_subplots
import gradio as gr
from ta.momentum import RSIIndicator
from ta.trend import MACD

# ------------------------
# Data Fetching
# ------------------------
def get_historical_data(symbol: str, timeframe: str = "1d", limit: int = 200) -> pd.DataFrame:
    """Fetch historical OHLCV data using CCXT (crypto) or yfinance (stocks)."""
    try:
        if "/" in symbol:
            exchange = ccxt.binance()
            ohlcv = exchange.fetch_ohlcv(symbol, timeframe, limit=limit)
            df = pd.DataFrame(ohlcv, columns=["timestamp", "Open", "High", "Low", "Close", "Volume"])
            df['timestamp'] = pd.to_datetime(df['timestamp'], unit='ms')
            df.set_index('timestamp', inplace=True)
        else:
            df = yf.download(symbol, period="1y", interval=timeframe)
        df['Returns'] = df['Close'].pct_change().fillna(0)
        return df
    except Exception as e:
        raise Exception(f"Data fetch failed for {symbol}: {str(e)}")

# ------------------------
# Indicators
# ------------------------
def add_indicators(df: pd.DataFrame) -> pd.DataFrame:
    df['SMA20'] = df['Close'].rolling(20).mean()
    df['SMA50'] = df['Close'].rolling(50).mean()
    df['Signal'] = np.where(df['SMA20'] > df['SMA50'], 'Buy', 'Sell')
    df['RSI'] = RSIIndicator(df['Close'], window=14).rsi()
    macd = MACD(df['Close'], window_slow=26, window_fast=12, window_sign=9)
    df['MACD'] = macd.macd()
    df['MACD_Signal'] = macd.macd_signal()
    return df

# ------------------------
# Chronos AI Prediction
# ------------------------
def make_chronos_prediction(df: pd.DataFrame, prediction_days: int = 7) -> dict:
    """Simulated Chronos AI predictions with confidence intervals."""
    returns = df['Returns'].values
    mean_pred = np.random.normal(np.mean(returns), np.std(returns), prediction_days)
    std_pred = np.full(prediction_days, np.std(returns))
    
    mean_pred = mean_pred * df['Close'].std() + df['Close'].mean()
    last_price = df['Close'].iloc[-1]
    price_predictions = [last_price]
    for ret in mean_pred:
        price_predictions.append(price_predictions[-1] * (1 + ret))
    price_predictions = np.array(price_predictions[1:])
    
    upper_bound = price_predictions * (1 + 1.96 * std_pred)
    lower_bound = price_predictions * (1 - 1.96 * std_pred)
    
    return {"mean": price_predictions, "upper": upper_bound, "lower": lower_bound}

# ------------------------
# Plotly Figure
# ------------------------
def create_prediction_plot(df: pd.DataFrame, predictions: dict, prediction_days: int) -> go.Figure:
    fig = make_subplots(
        rows=2, cols=1,
        subplot_titles=('Price Prediction', 'Technical Indicators'),
        vertical_spacing=0.15,
        row_width=[0.3, 0.7]
    )

    fig.add_trace(go.Scatter(x=df.index, y=df['Close'], name='Historical Price', line=dict(color='blue')), row=1, col=1)

    future_dates = pd.date_range(start=df.index[-1] + pd.Timedelta(1, unit='D'), periods=prediction_days)
    fig.add_trace(go.Scatter(x=future_dates, y=predictions['mean'], name='Predicted Price', line=dict(color='orange', width=3)), row=1, col=1)

    fig.add_trace(go.Scatter(
        x=list(future_dates) + list(future_dates[::-1]),
        y=list(predictions['upper']) + list(predictions['lower'][::-1]),
        fill='toself', fillcolor='rgba(255,127,14,0.2)',
        line=dict(color='rgba(255,255,255,0)'), name='Confidence Interval'
    ), row=1, col=1)

    fig.add_trace(go.Scatter(x=df.index, y=df['RSI'], name='RSI', line=dict(color='green')), row=2, col=1)
    fig.add_trace(go.Scatter(x=df.index, y=df['MACD'], name='MACD', line=dict(color='red')), row=2, col=1)
    fig.add_trace(go.Scatter(x=df.index, y=df['MACD_Signal'], name='MACD Signal', line=dict(color='purple')), row=2, col=1)

    fig.update_layout(
        title="📊 Price & Technical Predictions",
        height=800,
        showlegend=True,
        template="plotly_dark"
    )
    fig.update_yaxes(title_text="Price ($)", row=1, col=1)
    fig.update_yaxes(title_text="Indicator Value", row=2, col=1)
    return fig

# ------------------------
# Gradio Dashboard (Improved UX)
# ------------------------
def create_dashboard():
    with gr.Blocks(title="📈 Crypto & Stock Predictor") as demo:
        with gr.Row():
            with gr.Column(scale=1):
                gr.Markdown("## Input Parameters")
                symbol = gr.Textbox(label="Symbol", value="BTC/USDT", placeholder="e.g., BTC/USDT or AAPL", info="Enter crypto pair or stock symbol")
                timeframe = gr.Dropdown(label="Timeframe", choices=["1d", "1h", "15m"], value="1d", info="Select candle timeframe")
                prediction_days = gr.Slider(label="Prediction Days", minimum=1, maximum=30, value=7, step=1, info="How many days to predict")
                btn_predict = gr.Button("Predict", variant="primary")

            with gr.Column(scale=2):
                with gr.Tab("Predictions"):
                    plot = gr.Plot(label="Prediction Plot")
                with gr.Tab("Signals"):
                    signals_table = gr.Dataframe(label="SMA Signals", headers=["SMA20","SMA50","Signal"], interactive=False)
                with gr.Tab("Market Info"):
                    market_info = gr.JSON(label="Market Info")

        @btn_predict.click(inputs=[symbol, timeframe, prediction_days], outputs=[plot, signals_table, market_info])
        def update_dashboard(symbol, timeframe, prediction_days):
            df = get_historical_data(symbol, timeframe)
            df = add_indicators(df)
            predictions = make_chronos_prediction(df, prediction_days)
            fig = create_prediction_plot(df, predictions, prediction_days)
            signals_data = df[['SMA20','SMA50','Signal']].tail(prediction_days)

            info = {
                "Current Price": f"${df['Close'].iloc[-1]:.2f}",
                "RSI": f"{df['RSI'].iloc[-1]:.2f}",
                "MACD": f"{df['MACD'].iloc[-1]:.2f}",
                "MACD Signal": f"{df['MACD_Signal'].iloc[-1]:.2f}"
            }

            return fig, signals_data, info

    return demo

if __name__ == "__main__":
    demo = create_dashboard()
    demo.launch(server_name="0.0.0.0", server_port=7860)