Bitcoin Forum
September 14, 2025, 10:06:19 AM *
News: Latest Bitcoin Core release: 29.0 [Torrent]
 
   Home   Help Search Login Register More  
Pages: [1]
  Print  
Author Topic: A speculative exercise in Bitcoin  (Read 80 times)
mcdouglasx (OP)
Sr. Member
****
Offline Offline

Activity: 756
Merit: 408



View Profile WWW
May 27, 2025, 12:50:23 AM
 #1

Testing Google's AI. I decided to test how good it was at coding, and my overall experience was that it has improved but still leaves much to be desired.

However, if you know a bit about programming, it can serve as a fundamental tool to complement ideas.



As a speculative exercise, I created this script for a brief experiment in the forum.

The dynamic will be to make our speculative predictions and share their parameters to see, in a way, who was closest to the truth.

The sentiment bar remains in the middle by default, meaning there is no sentiment or expectation, this represents a neutral position.

The closer you get to the critical area, the more negative your sentiment becomes, indicating a downward trend. Conversely, as you approach the wonderful area, your sentiment becomes increasingly optimistic, translating into an upward-trending prediction.

Of course, this is not meant to be taken seriously due to the high volatility of the market, NOR SHOULD IT BE USED AS A TOOL IN A REALISTIC ENVIRONMENT.

You simply need to enter the estimated time, the percentage of sentiment used, and share the results.

Requirements:

- Python

Code:
pip install yfinance pandas numpy statsmodels scikit-learn arch prophet


code:

BtcTalk_forecast.py:

Code:
import tkinter as tk
from tkinter import ttk, messagebox
import yfinance as yf
import pandas as pd
import numpy as np
from statsmodels.tsa.arima.model import ARIMA
from statsmodels.tsa.statespace.sarimax import SARIMAX
from sklearn.linear_model import LinearRegression
from datetime import datetime, timedelta
import threading
import warnings

from arch import arch_model

try:
    from prophet import Prophet
    PROPHET_AVAILABLE = True
except ImportError:
    PROPHET_AVAILABLE = False
    print("Warning: The 'prophet' library is not installed. Prophet predictions will not be available.")
    print("To install it, run: pip install prophet")


warnings.filterwarnings("ignore", category=UserWarning, module='statsmodels')
warnings.filterwarnings("ignore", category=DeprecationWarning, module='numpy')
warnings.filterwarnings("ignore", category=UserWarning, module='statsmodels.base.model')


class BitcoinPredictor:
    def __init__(self):
        self.ticker = "BTC-USD"
        self.data = None
        self.MAX_SENTIMENT_IMPACT_PERCENTAGE = 0.30

    def fetch_data(self, period="max", interval="1d", progress_callback=None):
        try:
            if progress_callback:
                progress_callback("status", f"Starting historical data download for {self.ticker} (all available)...")
                progress_callback("progress", 10)

            print(f"Fetching {period} data for {self.ticker} from Yahoo Finance...")
            self.data = yf.download(self.ticker, period=period, interval=interval)

            if self.data.empty:
                if progress_callback:
                    progress_callback("status", "No data obtained. Check connection or ticker.", is_error=True)
                print("No data obtained. Check ticker or internet connection.")
                return False

            self.data.index = pd.to_datetime(self.data.index)
            self.data = self.data[~self.data.index.duplicated(keep='first')]

            if progress_callback:
                progress_callback("progress", 100)
                progress_callback("status", "Data successfully obtained.")
            print("Data successfully obtained.")
            return True
        except Exception as e:
            if progress_callback:
                progress_callback("status", f"Error fetching data: {e}", is_error=True)
            print(f"Error fetching data: {e}")
            return False

    def predict_price(self, interval_type, interval_value, sentiment_score=50.0):
        results = {
            "current_price": None,
            "sarima_prediction": None,
            "sarima_conf_int": None,
            "garch_volatility": None,
            "prophet_prediction": None,
            "prophet_conf_int": None,
            "linear_regression_prediction": None,
            "model_used": "N/A",
            "error": None,
            "adjusted_prediction": None,
            "sentiment_applied": True,
            "sentiment_value": None,
            "base_prediction_for_sentiment_avg": None
        }

        if self.data is None or self.data.empty:
            results["error"] = "Error: No historical data available. Please fetch data first."
            return results

        prices = self.data['Close'].dropna()
        if prices.empty:
            results["error"] = "Error: No valid closing prices in historical data."
            return results

        results["current_price"] = prices.iloc[-1].item()

        if interval_type == "day":
            forecast_steps_days = interval_value
        elif interval_type == "week":
            forecast_steps_days = interval_value * 7
        elif interval_type == "month":
            forecast_steps_days = interval_value * 30
        elif interval_type == "year":
            forecast_steps_days = interval_value * 365
        else:
            results["error"] = "Unsupported time interval."
            return results

        try:
            if len(prices) < 30:
                results["sarima_prediction"] = "Insufficient data for SARIMA."
                results["sarima_conf_int"] = "N/A"
            else:
                sarima_model = SARIMAX(prices, order=(5,1,0), seasonal_order=(1,1,0,7),
                                        enforce_stationarity=False, enforce_invertibility=False)
                sarima_model_fit = sarima_model.fit(disp=False)
                sarima_forecast = sarima_model_fit.get_forecast(steps=forecast_steps_days)
                sarima_predicted_mean = sarima_forecast.predicted_mean.iloc[-1].item()
                sarima_conf_int = sarima_forecast.conf_int(alpha=0.05).iloc[-1]
               
                results["sarima_prediction"] = sarima_predicted_mean
                results["sarima_conf_int"] = (sarima_conf_int.iloc[0].item(), sarima_conf_int.iloc[1].item())

                try:
                    residuals = sarima_model_fit.resid
                    garch_model = arch_model(residuals, vol='Garch', p=1, q=1, rescale=True)
                    garch_results = garch_model.fit(disp='off')
                   
                    garch_forecast = garch_results.variance.iloc[-1]
                    forecasted_variance = garch_forecast.item()
                    results["garch_volatility"] = np.sqrt(forecasted_variance)
                except Exception as e_garch:
                    results["garch_volatility"] = f"GARCH Error: {e_garch}"
                    print(f"GARCH Error: {e_garch}")

        except Exception as e_sarima:
            results["sarima_prediction"] = f"SARIMA Error: {e_sarima}"
            results["sarima_conf_int"] = "N/A"
            results["garch_volatility"] = "N/A"
            print(f"SARIMA Error: {e_sarima}")

        if PROPHET_AVAILABLE:
            try:
                df_prophet = prices.reset_index()
                df_prophet.columns = ['ds', 'y']
                df_prophet['ds'] = pd.to_datetime(df_prophet['ds'])

                prophet_model = Prophet(
                    seasonality_mode='multiplicative',
                    yearly_seasonality=True,
                    weekly_seasonality=True,
                    daily_seasonality=False
                )
                prophet_model.fit(df_prophet)

                future_dates = [prices.index[-1] + timedelta(days=i) for i in range(1, forecast_steps_days + 1)]
                future = pd.DataFrame({'ds': future_dates})
               
                prophet_forecast = prophet_model.predict(future)
               
                prophet_predicted_price = prophet_forecast['yhat'].iloc[-1].item()
                prophet_lower_bound = prophet_forecast['yhat_lower'].iloc[-1].item()
                prophet_upper_bound = prophet_forecast['yhat_upper'].iloc[-1].item()

                results["prophet_prediction"] = prophet_predicted_price
                results["prophet_conf_int"] = (prophet_lower_bound, prophet_upper_bound)

            except Exception as e_prophet:
                results["prophet_prediction"] = f"Prophet Error: {e_prophet}"
                results["prophet_conf_int"] = "N/A"
                print(f"Prophet Error: {e_prophet}")
        else:
            results["prophet_prediction"] = "Prophet not available (library not installed)."
            results["prophet_conf_int"] = "N/A"

        linear_regression_price = None
        if interval_type == "year":
            try:
                positive_prices = prices[prices > 0]
                log_prices = np.log(positive_prices)
               
                time_index_filtered = np.arange(len(positive_prices)).reshape(-1, 1)

                if len(log_prices) > 1:
                    model_lr = LinearRegression()
                    model_lr.fit(time_index_filtered, log_prices)

                    future_days_offset = interval_value * 365
                    last_day_index_filtered = len(positive_prices) - 1
                    future_index = np.array([[last_day_index_filtered + future_days_offset]])
                   
                    predicted_log_price = model_lr.predict(future_index)[0]
                    linear_regression_price = np.exp(predicted_log_price).item()
                    results["linear_regression_prediction"] = linear_regression_price
                else:
                    results["linear_regression_prediction"] = "Insufficient data for Linear Regression."
            except Exception as e_lr:
                results["linear_regression_prediction"] = f"Linear Regression Error: {e_lr}"
                print(f"Linear Regression Error: {e_lr}")
        else:
            results["linear_regression_prediction"] = "Linear Regression not applicable for this interval."
       
        valid_predictions = []
        model_names_used = []

        if isinstance(results["sarima_prediction"], (float, int)):
            valid_predictions.append(results["sarima_prediction"])
            model_names_used.append("SARIMA")
       
        if isinstance(results["prophet_prediction"], (float, int)):
            valid_predictions.append(results["prophet_prediction"])
            model_names_used.append("Prophet")
           
        if isinstance(results["linear_regression_prediction"], (float, int)):
            valid_predictions.append(results["linear_regression_prediction"])
            model_names_used.append("Log-Linear Regression")

        base_prediction = None
        if valid_predictions:
            base_prediction = np.mean(valid_predictions)
            results["model_used"] = f"Average of: {', '.join(model_names_used)}"
        else:
            base_prediction = results["current_price"]
            results["model_used"] = "None (model error, using current price)"

        results["base_prediction_for_sentiment_avg"] = base_prediction

        if base_prediction is not None:
            normalized_sentiment = (sentiment_score - 50) / 50
            adjustment_factor = normalized_sentiment * self.MAX_SENTIMENT_IMPACT_PERCENTAGE
            results["adjusted_prediction"] = base_prediction * (1 + adjustment_factor)
            results["sentiment_value"] = sentiment_score
        else:
            results["adjusted_prediction"] = base_prediction
            results["sentiment_value"] = None

        return results


class BitcoinForecastApp:
    def __init__(self, master):
        self.master = master
        master.title("BtcTalk Sandbox: Bitcoin Price Experiment")
        master.geometry("700x850")
        master.resizable(False, False)

        self.predictor = BitcoinPredictor()
        self.prediction_intervals = {
            "1 day": ("day", 1),
            "1 week": ("week", 1),
            "1 month": ("month", 1),
            "3 months": ("month", 3),
            "6 months": ("month", 6),
            "1 year": ("year", 1),
            "2 years": ("year", 2),
            "3 years": ("year", 3),
            "4 years": ("year", 4),
            "5 years": ("year", 5),
        }
        self.data_loaded = False
        self.style = ttk.Style()

        self._create_widgets()
        self._load_initial_data_threaded()

    def _display_message(self, message, is_error=False):
        if hasattr(self, 'status_label'):
            self.status_label.config(text=message, foreground='red' if is_error else 'gray')
            self.master.update_idletasks()

    def _create_widgets(self):
        self.style.theme_use('clam')
        self.style.configure('TFrame', background='#f0f0f0')
        self.style.configure('TLabel', background='#f0f0f0', font=('Inter', 10))
        self.style.configure('TButton', font=('Inter', 10, 'bold'), padding=10, relief='raised', borderwidth=2)
        self.style.map('TButton', background=[('active', '#e0e0e0')])
        self.style.configure('TCombobox', font=('Inter', 10))
        self.style.configure('Horizontal.TProgressbar', thickness=15)
        self.style.configure('Sentiment.Horizontal.TScale', background='lightgray', troughcolor='#AAAAAA')
        self.style.map('Sentiment.Horizontal.TScale', background=[('active', 'lightgray')])


        main_frame = ttk.Frame(self.master, padding="20 20 20 20")
        main_frame.pack(fill=tk.BOTH, expand=True)

        title_label = ttk.Label(main_frame, text="BtcTalk Sandbox: Bitcoin Price Experiment (BTC-USD)", font=('Inter', 16, 'bold'), foreground='#333')
        title_label.grid(row=0, column=0, columnspan=3, pady=(0, 20))

        self.progress_frame = ttk.Frame(main_frame)
        self.progress_frame.grid(row=1, column=0, columnspan=3, pady=(10, 5), sticky="ew")

        self.progress_bar = ttk.Progressbar(self.progress_frame, orient="horizontal", length=400, mode="determinate", style="Horizontal.TProgressbar")
        self.progress_bar.pack(pady=5, fill=tk.X, expand=True)

        self.loading_status_label = ttk.Label(self.progress_frame, text="Loading data...", font=('Inter', 9, 'italic'), foreground='blue')
        self.loading_status_label.pack(pady=2)

        ttk.Label(main_frame, text="Prediction Interval:").grid(row=2, column=0, padx=5, pady=5, sticky="w")
        self.interval_combobox = ttk.Combobox(main_frame, state="readonly", width=25)
        self.interval_combobox['values'] = list(self.prediction_intervals.keys())
        self.interval_combobox.grid(row=2, column=1, columnspan=2, padx=5, pady=5, sticky="ew")
        self.interval_combobox.set("1 day")

        sentiment_frame = ttk.LabelFrame(main_frame, text="Custom Sentiment Adjustment", padding="15 15 15 15")
        sentiment_frame.grid(row=3, column=0, columnspan=3, padx=10, pady=10, sticky="ew")

        self.sentiment_label_info = ttk.Label(sentiment_frame, text="0=Critical (pessimistic) | 50=Neutral | 100=Wonderful (optimistic)", font=('Inter', 9, 'italic'), foreground='gray')
        self.sentiment_label_info.grid(row=0, column=0, columnspan=3, pady=(0,5), sticky="w")

        self.critical_label = ttk.Label(sentiment_frame, text="0 (Critical)", foreground="black", font=('Inter', 9, 'bold'))
        self.critical_label.grid(row=1, column=0, padx=(5,0), pady=5, sticky="w")

        self.sentiment_scale_var = tk.DoubleVar(value=50.0)
        self.sentiment_slider = ttk.Scale(sentiment_frame,
                                          from_=0, to=100,
                                          orient=tk.HORIZONTAL,
                                          variable=self.sentiment_scale_var,
                                          length=300,
                                          command=self._update_sentiment_label,
                                          style='Sentiment.Horizontal.TScale')
        self.sentiment_slider.grid(row=1, column=1, padx=5, pady=5, sticky="ew")
        self.sentiment_slider.bind("<ButtonRelease-1>", self._update_sentiment_label_on_release)

        self.wonderful_label = ttk.Label(sentiment_frame, text="100 (Wonderful)", foreground="black", font=('Inter', 9, 'bold'))
        self.wonderful_label.grid(row=1, column=2, padx=(0,5), pady=5, sticky="e")

        self.sentiment_value_display_label = ttk.Label(sentiment_frame, text="Sentiment: 50 (Neutral)", font=('Inter', 10, 'bold'))
        self.sentiment_value_display_label.grid(row=2, column=0, columnspan=3, padx=5, pady=5, sticky="w")
       
        sentiment_frame.grid_columnconfigure(1, weight=1)

        self.predict_button = ttk.Button(main_frame, text="Predict Price", command=self._on_predict_click, state=tk.DISABLED)
        self.predict_button.grid(row=4, column=0, columnspan=3, pady=20)

        results_frame = ttk.LabelFrame(main_frame, text="Detailed Forecast Results", padding="15 15 15 15")
        results_frame.grid(row=5, column=0, columnspan=3, padx=10, pady=10, sticky="ew")

        self.results_text = tk.Text(results_frame, height=15, width=70, state="disabled", font=('Inter', 10), wrap=tk.WORD)
        self.results_text.grid(row=0, column=0, padx=5, pady=5, sticky="nsew")
        results_frame.grid_rowconfigure(0, weight=1)
        results_frame.grid_columnconfigure(0, weight=1)

        self.status_label = ttk.Label(main_frame, text="Waiting for data load...", font=('Inter', 9, 'italic'), foreground='gray')
        self.status_label.grid(row=6, column=0, columnspan=3, pady=(10, 0))

        disclaimer_text = ("Disclaimer: Cryptocurrency price predictions are inherently speculative and should not be considered financial advice. "
                           "Mathematical models are based on historical price data and cannot predict unpredictable future events or directly incorporate external factors "
                           "(such as market sentiment, political actions, economic news, or regulatory changes). "
                           "This application is for demonstrative and educational purposes only. Forecasted volatility is an estimate of risk, not a guarantee.")
        self.disclaimer_label = ttk.Label(main_frame, text=disclaimer_text, font=('Inter', 8, 'italic'), foreground='red', wraplength=650, justify=tk.LEFT)
        self.disclaimer_label.grid(row=7, column=0, columnspan=3, pady=(10, 0), sticky="ew")

        main_frame.grid_columnconfigure(0, weight=1)
        main_frame.grid_columnconfigure(1, weight=1)
        main_frame.grid_columnconfigure(2, weight=1)

    def _update_sentiment_label(self, val):
        sentiment_val = int(float(val))
        if sentiment_val == 50:
            sentiment_text = "Neutral"
        elif sentiment_val > 50:
            sentiment_text = "Optimistic"
        else:
            sentiment_text = "Pessimistic"
        self.sentiment_value_display_label.config(text=f"Sentiment: {sentiment_val} ({sentiment_text})")

    def _update_sentiment_label_on_release(self, event):
        sentiment_val = int(self.sentiment_scale_var.get())
       
        if sentiment_val < 50:
            trough_color = '#FF6666'
        elif sentiment_val > 50:
            trough_color = '#66FF66'
        else:
            trough_color = '#AAAAAA'

        self.style.configure('Sentiment.Horizontal.TScale', troughcolor=trough_color)


    def _update_loading_progress(self, type, value, is_error=False):
        if hasattr(self, 'progress_bar') and hasattr(self, 'loading_status_label'):
            if type == "progress":
                self.progress_bar['value'] = value
            elif type == "status":
                self.loading_status_label.config(text=value, foreground='red' if is_error else 'blue')
            self.master.update_idletasks()

    def _load_initial_data_threaded(self):
        self.predict_button.config(state=tk.DISABLED)
        self.interval_combobox.config(state=tk.DISABLED)

        self._display_message("Starting Bitcoin historical data load...", False)
       
        threading.Thread(target=self._perform_data_load, daemon=True).start()

    def _perform_data_load(self):
        success = self.predictor.fetch_data(period="max", progress_callback=self._update_loading_progress)
       
        self.master.after(0, self._after_data_load, success)

    def _after_data_load(self, success):
        if success:
            self.data_loaded = True
            self._display_message("Bitcoin historical data loaded successfully. Ready to predict!", False)
            self.predict_button.config(state=tk.NORMAL)
            self.interval_combobox.config(state="readonly")
            self._update_sentiment_label_on_release(None)

        else:
            self.data_loaded = False
            self._display_message("Error loading historical data. Application will not function correctly.", True)
            self.predict_button.config(state=tk.DISABLED)
            self.interval_combobox.config(state=tk.DISABLED)
            self.loading_status_label.config(text="ERROR: Failed to load data.")


    def _on_predict_click(self):
        if not self.data_loaded:
            self._display_message("Historical data has not been loaded yet. Please wait.", True)
            return

        selected_interval_text = self.interval_combobox.get()
        interval_type, interval_value = self.prediction_intervals.get(selected_interval_text)

        if not interval_type:
            self._display_message("Please select a valid prediction interval.", True)
            return

        sentiment_score = self.sentiment_scale_var.get()

        self._display_message(f"Performing prediction for {selected_interval_text}...", False)
        self.predict_button.config(state=tk.DISABLED)
        self.sentiment_slider.config(state=tk.DISABLED)
        self.sentiment_value_display_label.config(state=tk.DISABLED)
        self.critical_label.config(state=tk.DISABLED)
        self.wonderful_label.config(state=tk.DISABLED)

        try:
            prediction_results = self.predictor.predict_price(
                interval_type,
                interval_value,
                sentiment_score
            )

            self.results_text.config(state="normal")
            self.results_text.delete(1.0, tk.END)

            if prediction_results["error"]:
                output = f"Prediction Error: {prediction_results['error']}\n"
                self.results_text.insert(tk.END, output)
                self.results_text.config(state="disabled")
                self._display_message("Prediction completed with errors.", is_error=True)
                return

            output = f"Current BTC-USD Price: ${prediction_results['current_price']:,.2f}\n"
            output += f"--------------------------------------------------\n\n"

            if prediction_results["sarima_prediction"] is not None and not isinstance(prediction_results["sarima_prediction"], str):
                output += f"SARIMA Prediction for {selected_interval_text}: ${prediction_results['sarima_prediction']:,.2f}\n"
                if prediction_results["sarima_conf_int"] and isinstance(prediction_results["sarima_conf_int"], tuple):
                    lower, upper = prediction_results["sarima_conf_int"]
                    output += f"  SARIMA Confidence Interval (95%): [${lower:,.2f}, ${upper:,.2f}]\n"
                if prediction_results["garch_volatility"] is not None and not isinstance(prediction_results["garch_volatility"], str):
                    output += f"  Forecasted Volatility (GARCH): {prediction_results['garch_volatility'] * 100:,.2f}% (standard deviation)\n"
                output += "\n"
            else:
                output += f"SARIMA: {prediction_results['sarima_prediction']}\n\n"

            if prediction_results["prophet_prediction"] is not None and not isinstance(prediction_results["prophet_prediction"], str):
                output += f"Prophet Prediction for {selected_interval_text}: ${prediction_results['prophet_prediction']:,.2f}\n"
                if prediction_results["prophet_conf_int"] and isinstance(prediction_results["prophet_conf_int"], tuple):
                    lower, upper = prediction_results["prophet_conf_int"]
                    output += f"  Prophet Confidence Interval (80% default): [${lower:,.2f}, ${upper:,.2f}]\n"
                output += "\n"
            else:
                output += f"Prophet: {prediction_results['prophet_prediction']}\n\n"

            if prediction_results["linear_regression_prediction"] is not None:
                if not isinstance(prediction_results["linear_regression_prediction"], str):
                    output += f"Log-Linear Regression Prediction for {selected_interval_text}: ${prediction_results['linear_regression_prediction']:,.2f}\n\n"
                else:
                    output += f"Log-Linear Regression: {prediction_results['linear_regression_prediction']}\n\n"
           
            output += f"--- Custom Sentiment Adjusted Prediction ---\n"
            output += f"Sentiment applied: {int(prediction_results['sentiment_value'])} (0=Critical, 100=Wonderful)\n"
            output += f"Base for Adjustment (Average of Valid Models): ${prediction_results['base_prediction_for_sentiment_avg']:,.2f}\n"
            output += f"Final Adjusted Prediction: ${prediction_results['adjusted_prediction']:,.2f}\n"
            output += f"----------------------------------------------------------\n\n"
           
            output += f"--------------------------------------------------\n"
            output += f"Base Model(s) Used for Point Prediction: {prediction_results['model_used']}\n"
            output += "Based on historical data from Yahoo Finance.\n"

            prices = self.predictor.data['Close'].dropna()
            if len(prices) > 1 and (prices.index[-1] - prices.index[0]).days > 365:
                first_price = prices.iloc[0].item()
                last_price_historical = prices.iloc[-1].item()
                num_years = (prices.index[-1] - prices.index[0]).days / 365.25
                if first_price > 0 and num_years > 0:
                    try:
                        cagr = ((last_price_historical / first_price)**(1/num_years) - 1) * 100
                        output += f"Historical CAGR (last {num_years:.1f} years): {cagr:,.2f}%\n"
                    except OverflowError:
                        output += "Historical CAGR: Too large to calculate or inconsistent data.\n"
                else:
                    output += "Historical CAGR: Insufficient data for calculation.\n"
            else:
                output += "Historical CAGR: Not applicable (less than 1 year of data or insufficient data).\n"

            self.results_text.insert(tk.END, output)
            self.results_text.config(state="disabled")
            self._display_message("Prediction completed.")

        except Exception as e:
            self._display_message(f"An unexpected error occurred during prediction: {e}. Check console for more details.", True)
            print(f"Prediction error detail: {e}")
        finally:
            self.predict_button.config(state=tk.NORMAL)
            self.sentiment_slider.config(state=tk.NORMAL)
            self.sentiment_value_display_label.config(state=tk.NORMAL)
            self.critical_label.config(state=tk.NORMAL)
            self.wonderful_label.config(state=tk.NORMAL)
            self.sentiment_label_info.config(state=tk.NORMAL)

if __name__ == "__main__":
    root = tk.Tk()
    app = BitcoinForecastApp(root)
    root.mainloop()



My Bet:




Both SARIMA and Prophet are widely used time series forecasting models for predicting Bitcoin prices.

A study found that SARIMA performs better for daily Bitcoin predictions, while Prophet yields more accurate results for monthly predictions:

A Comparative Study between the Facebook Prophet Model and SARIMA for Bitcoin Price Prediction




This script uses yfinance to collect Bitcoin's historical data.

▄▄█████████████████▄▄
▄█████████████████████▄
███▀▀█████▀▀░░▀▀███████

██▄░░▀▀░░▄▄██▄░░█████
█████░░░████████░░█████
████▌░▄░░█████▀░░██████
███▌░▐█▌░░▀▀▀▀░░▄██████
███░░▌██░░▄░░▄█████████
███▌░▀▄▀░░█▄░░█████████
████▄░░░▄███▄░░▀▀█▀▀███
██████████████▄▄░░░▄███
▀█████████████████████▀
▀▀█████████████████▀▀
Rainbet.com
CRYPTO CASINO & SPORTSBOOK
|
█▄█▄█▄███████▄█▄█▄█
███████████████████
███████████████████
███████████████████
█████▀█▀▀▄▄▄▀██████
█████▀▄▀████░██████
█████░██░█▀▄███████
████▄▀▀▄▄▀███████
█████████▄▀▄███
█████████████████
███████████████████
██████████████████
███████████████████
 
 $20,000 
WEEKLY RAFFLE
|



█████████
█████████ ██
▄▄█░▄░▄█▄░▄░█▄▄
▀██░▐█████▌░██▀
▄█▄░▀▀▀▀▀░▄█▄
▀▀▀█▄▄░▄▄█▀▀▀
▀█▀░▀█▀
10K
WEEKLY
RACE
100K
MONTHLY
RACE
|

██









█████
███████
███████
█▄
██████
████▄▄
█████████████▄
███████████████▄
░▄████████████████▄
▄██████████████████▄
███████████████▀████
██████████▀██████████
██████████████████
░█████████████████▀
░░▀███████████████▀
████▀▀███
███████▀▀
████████████████████   ██
 
[..►PLAY..]
 
████████   ██████████████
mcdouglasx (OP)
Sr. Member
****
Offline Offline

Activity: 756
Merit: 408



View Profile WWW
June 03, 2025, 05:56:55 AM
 #2

The prediction that is approaching reality was as follows: $104,710.00 USD current price on June 3.


▄▄█████████████████▄▄
▄█████████████████████▄
███▀▀█████▀▀░░▀▀███████

██▄░░▀▀░░▄▄██▄░░█████
█████░░░████████░░█████
████▌░▄░░█████▀░░██████
███▌░▐█▌░░▀▀▀▀░░▄██████
███░░▌██░░▄░░▄█████████
███▌░▀▄▀░░█▄░░█████████
████▄░░░▄███▄░░▀▀█▀▀███
██████████████▄▄░░░▄███
▀█████████████████████▀
▀▀█████████████████▀▀
Rainbet.com
CRYPTO CASINO & SPORTSBOOK
|
█▄█▄█▄███████▄█▄█▄█
███████████████████
███████████████████
███████████████████
█████▀█▀▀▄▄▄▀██████
█████▀▄▀████░██████
█████░██░█▀▄███████
████▄▀▀▄▄▀███████
█████████▄▀▄███
█████████████████
███████████████████
██████████████████
███████████████████
 
 $20,000 
WEEKLY RAFFLE
|



█████████
█████████ ██
▄▄█░▄░▄█▄░▄░█▄▄
▀██░▐█████▌░██▀
▄█▄░▀▀▀▀▀░▄█▄
▀▀▀█▄▄░▄▄█▀▀▀
▀█▀░▀█▀
10K
WEEKLY
RACE
100K
MONTHLY
RACE
|

██









█████
███████
███████
█▄
██████
████▄▄
█████████████▄
███████████████▄
░▄████████████████▄
▄██████████████████▄
███████████████▀████
██████████▀██████████
██████████████████
░█████████████████▀
░░▀███████████████▀
████▀▀███
███████▀▀
████████████████████   ██
 
[..►PLAY..]
 
████████   ██████████████
Pages: [1]
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.19 | SMF © 2006-2009, Simple Machines Valid XHTML 1.0! Valid CSS!