Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updated the Script for User Friendliness #1

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions BTCUSDT_predictions.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
,Model 1,Model 2,Model 3,Model 4
0,63919.35250000008,64262.7,63908.37834900037,63840.04536619295
1,63423.25429999992,63152.01,63659.1707101622,63869.0389345954
2,65011.0950000001,65173.99,65014.57449067909,64552.76661555629
3,65660.47850000008,65769.95,65870.51656146956,65699.04049608468
4,65769.97089999999,65858.0,65773.77101660996,65868.47218892295
5,65565.34639999991,65602.01,65613.15961152391,65846.58070227425
6,63570.34319999994,63327.59,63641.94846348572,64265.206929840926
7,61297.37070000002,60805.78,61771.543690837556,62176.306500999766
8,60944.10550000003,60649.28,61534.934782153476,61374.58113794234
9,60738.67029999998,60752.71,60688.189725915814,60712.640070678615
10,61761.47590000002,62086.0,61937.26222859245,61660.19218442663
11,62065.076300000015,62058.0,61899.53361315821,62009.28258436733
12,62632.12420000006,62819.91,62527.3250838097,62461.66321806782
13,62498.7231,62224.0,63600.12523207192,63355.616200261706
14,62263.82590000009,62160.49,62636.08780019019,62521.448614304965
15,60854.69439999994,60636.02,61071.78310790617,61360.46045651742
16,60342.635399999934,60326.39,59908.79966274048,60026.65307039782
17,62291.43989999998,62540.0,62675.830201943,61950.334281343516
18,63145.033999999985,63206.22,63081.48889013403,62890.30474420209
19,62705.33739999991,62870.02,62258.20326144328,62468.333053275805
20,65821.8547000001,66083.99,65589.0249382245,64837.914767528484
21,67016.85639999995,67074.14,66671.4704391068,66593.74607362071
22,67729.3118999999,67620.01,67829.04104327965,67725.99301787547
23,67412.25690000004,67421.78,67059.39845251033,67327.04957688058
24,68286.07669999998,68428.0,68435.02049263423,68223.88474096541
25,68516.87600000002,68378.0,68160.33558887534,68324.97185214274
26,68882.26350000009,69031.99,68870.69962816169,68802.72221711298
27,67630.0641,67377.5,67766.39120386967,68104.99534838935
28,67346.69970000001,67426.0,67081.28148397617,67282.25415273676
29,66685.0858,66473.0,66525.79468248309,66951.00763572242
18 changes: 16 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Crypto Price Prediction Bot

Crypto Price Prediction Bot is a Telegram bot that predicts the price of cryptocurrencies using historical data from the Binance exchange. It utilizes machine learning models to analyze the data and generate price predictions for the next 30 days.
The **Crypto Price Prediction Bot** is a Telegram bot designed to predict the prices of cryptocurrencies using historical data from the Binance exchange. It leverages machine learning models to analyze data and generate price predictions for the next 30 days, along with interactive visualizations.

## Getting Started

Expand All @@ -19,10 +19,23 @@ To get started with the Crypto Price Prediction Bot, you need to set up a Telegr
5. Enter the symbol of the cryptocurrency you want to predict (e.g., BTCUSDT).
6. The bot will process the data, train the models, and generate price predictions.
7. The bot will send you a CSV file containing the predictions for the next 30 days.
8. **Download CSV File**: The bot will send you a CSV file containing the predictions for the next 30 days.
9. **View Interactive Graphs**: The bot will also generate interactive graphs displaying the predictions from different models.

## Features

- **Data Retrieval**: Fetches historical price data from the Binance exchange.
- **Data Cleaning**: Cleans and processes the data by calculating RSI, Moving Average, and MACD indicators.
- **Machine Learning Models**: Trains multiple models including Random Forest, Decision Tree, Linear Regression, and Ridge regression.
- **Price Prediction**: Predicts prices for the next 30 days based on historical data.
- **Interactive Visualizations**: Uses Plotly to create interactive plots for a more engaging user experience.

![Screenshot 2024-10-23 165824](https://github.com/user-attachments/assets/6dd17aca-82bc-4ddd-aa80-3e94bc93884e)


## File Description

- `bot.py`: The main Python script that implements the Telegram bot and handles user interactions.
- `main.py`: The main Python script that implements the Telegram bot and handles user interactions.
- `ccxt`: A Python library for cryptocurrency trading and market data retrieval from various exchanges.
- `numpy`: A library for scientific computing with Python.
- `pandas`: A library for data manipulation and analysis.
Expand All @@ -33,6 +46,7 @@ To get started with the Crypto Price Prediction Bot, you need to set up a Telegr
## Contributors

- [Sheekovic](https://github.com/Sheekovic)
- [Aas1kk](https://github.com/aa-sikkkk)

Feel free to contribute to the project by creating issues or submitting pull requests.

Expand Down
143 changes: 71 additions & 72 deletions main.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import ccxt
import numpy as np
import pandas as pd
import plotly.graph_objects as go
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.impute import SimpleImputer
Expand All @@ -15,7 +16,7 @@
from telebot.types import Message

# Initialize the Telegram bot
bot = telebot.TeleBot('PUT YOUR BOT TOKEN HERE')
bot = telebot.TeleBot('YOUR_TOKEN_HERE')
print('Bot started')

# Function to get the crypto symbol from the user
Expand All @@ -26,49 +27,30 @@ def get_crypto_symbol(message: Message):
# Import Bitcoin Price Data from Binance
def get_binance_data(crypto_symbol):
print(f"Getting {crypto_symbol} data from Binance...")
# Create a Binance exchange instance
binance = ccxt.binance()

# Define the symbol and timeframe
symbol = crypto_symbol
timeframe = '1d'

# Fetch OHLCV (Open-High-Low-Close-Volume) data
ohlcv = binance.fetch_ohlcv(symbol, timeframe, limit=1000)

# if data is not empty
if ohlcv:
# Create a DataFrame
df = pd.DataFrame(ohlcv, columns=['Open Time', 'Open', 'High', 'Low', 'Close', 'Volume'])

# Convert the timestamp to datetime
df['Open Time'] = pd.to_datetime(df['Open Time'], unit='ms')

# Set the index to the date column
df.set_index('Open Time', inplace=True)

# Convert the columns to numeric
df = df.apply(pd.to_numeric)

# Return the DataFrame
return df
else:
print('No data found')
return None

# Save the data to a CSV file
def save_data(df, crypto_symbol):
# Save the data to a CSV file
df.to_csv(f'{crypto_symbol}.csv')
print(f"Data saved to {crypto_symbol}.csv")

os.remove(f'{crypto_symbol}.csv')

# Load the data from a CSV file
def load_data(crypto_symbol):
# Load the data from a CSV file
df = pd.read_csv(f'{crypto_symbol}.csv', index_col='Open Time', parse_dates=True)
# Return the DataFrame
return df

# Calculate RSI
Expand All @@ -84,117 +66,140 @@ def calculate_rsi(data, window=14):

# Clean the data
def clean_data(df):
# Drop the rows with missing values
df.dropna(inplace=True)
# Drop the duplicate rows
df.drop_duplicates(inplace=True)

# Calculate RSI
df['RSI'] = calculate_rsi(df['Close'], window=14)

# Calculate Moving Average
df['MA'] = df['Close'].rolling(window=20).mean()

# Calculate MACD
macd = MACD(df['Close'], window_slow=26, window_fast=12, window_sign=9)
df['MACD'] = macd.macd()

# Return the cleaned DataFrame
return df

# Train the model with the data
def train_model(df):
# Create the features and target
X = df.drop('Close', axis=1)
y = df['Close']
# Split the data into training and testing sets
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# Define the column transformer
column_transformer = make_column_transformer(
(SimpleImputer(), X_train.columns),
remainder='passthrough'
)

# Create a list of models
models = [
('Random Forest', make_pipeline(column_transformer, RandomForestRegressor())),
('Decision Tree', make_pipeline(column_transformer, DecisionTreeRegressor())),
('Linear Regression', make_pipeline(column_transformer, LinearRegression())),
('Ridge', make_pipeline(column_transformer, Ridge()))
]

# Create a dictionary to store the model scores
model_scores = {}

# Loop through the models
for name, model in models:
# Fit the model to the data
model.fit(X_train, y_train)
# Evaluate the model and store its score
score = model.score(X_test, y_test)
model_scores[name] = score

# Return the model scores
return model_scores


# Print the model scores
def print_model_scores(model_scores):
# Loop through the model names and scores and print them
for i, (name, score) in enumerate(model_scores.items()):
model_name = list(model_scores.keys())[i] # Extract the model name from the keys
model_name = list(model_scores.keys())[i]
print(f'{model_name} Model R-squared: {score*100:.2f}%')

# Predict the price for the next 30 days
def predict_price(df):
# Create the features and target
X = df.drop('Close', axis=1)
y = df['Close']

# Impute missing values
imputer = SimpleImputer()
X = imputer.fit_transform(X)

# Scale the data
scaler = StandardScaler()
scaler.fit(X)
X = scaler.transform(X)

# Create a list of models
models = [
('Random Forest', RandomForestRegressor()),
('Decision Tree', DecisionTreeRegressor()),
('Linear Regression', LinearRegression()),
('Ridge', Ridge())
]
# Create a list to store the predictions

predictions = []
# Loop through the models
for name, model in models:
# Fit the model to the data
model.fit(X, y)
# Predict the price for the next 30 days
prediction = model.predict(X[-30:])
# Append the predictions to the list
predictions.append(prediction)
# Convert the predictions list to a numpy array

predictions = np.array(predictions).T
# Return the predictions
return predictions

# Save the predictions to a symbol name.csv file
def save_predictions(predictions, crypto_symbol, file_name):
# Create a DataFrame
df = pd.DataFrame(predictions)
# Get the model names based on the number of columns
model_names = [f'Model {i+1}' for i in range(predictions.shape[1])]
# Set the columns of the DataFrame
df.columns = model_names
# Save the predictions to a CSV file
df.to_csv(file_name)
print(f"Predictions saved to {file_name}")

# Advanced interactive plot with Plotly (Dropdown, Range Slider, Annotations)
def plot_predictions_advanced(crypto_symbol, file_name):
predictions_df = pd.read_csv(file_name)

# Create a figure
fig = go.Figure()

# Add traces for each model's predictions
for column in predictions_df.columns[1:]:
fig.add_trace(go.Scatter(
x=predictions_df.index,
y=predictions_df[column],
mode='lines+markers',
name=column,
visible=True if column == 'Model 1' else False # Set only Model 1 visible initially
))

# Dropdown menu for selecting models to display
dropdown_buttons = []
for column in predictions_df.columns[1:]:
dropdown_buttons.append(dict(
args=[{'visible': [col == column for col in predictions_df.columns[1:]]}],
label=column,
method='restyle'
))

fig.update_layout(
updatemenus=[
dict(
active=0,
buttons=dropdown_buttons,
x=1.15, # Place it to the right
y=0.5
)
]
)

# Range slider
fig.update_layout(
xaxis=dict(
rangeslider=dict(
visible=True
)
)
)

# Add title and labels
fig.update_layout(
title=f'Predictions for {crypto_symbol} - Model Comparison',
xaxis_title='Days',
yaxis_title='Predicted Price',
template='plotly_white',
hovermode='x unified',
legend_title_text='Models',
)

# Show the interactive plot in the browser or supported terminal
fig.show()

# Handle the '/start' command
@bot.message_handler(commands=['start'])
def handle_start(message):
Expand All @@ -203,37 +208,31 @@ def handle_start(message):
# Handle the '/predict' command
@bot.message_handler(commands=['predict'])
def handle_predict(message):
# Ask the user for the symbol of the cryptocurrency
bot.reply_to(message, "Enter the symbol of the cryptocurrency (e.g., BTCUSDT):")
# Register the next handler to receive the symbol from the user
bot.register_next_step_handler(message, process_crypto_symbol)


# Process the cryptocurrency symbol
def process_crypto_symbol(message):
crypto_symbol = message.text
# Get the data from Binance
data = get_binance_data(crypto_symbol)
if data is not None:
# Clean the data
cleaned_data = clean_data(data)
# Train the model
model_scores = train_model(cleaned_data)
# Print the model scores
print_model_scores(model_scores)
# Predict the price for the next 30 days
predictions = predict_price(cleaned_data)
# Save the predictions to a CSV file

# Save CSV in both Telegram and root folder
file_name = f'{crypto_symbol}_predictions.csv'
save_predictions(predictions, crypto_symbol, file_name)
# Send the predictions file to the user

# Send the CSV to Telegram chat
bot.send_document(message.chat.id, open(file_name, 'rb'))
# Delete the CSV file
os.remove(file_name)

# Plot predictions interactively
plot_predictions_advanced(crypto_symbol, file_name)
else:
bot.reply_to(message, "No data found for the given cryptocurrency symbol.")


# Handle all other messages
@bot.message_handler(func=lambda message: True)
def handle_message(message):
Expand Down