added in MyLibs from private Mt5 repo
This commit is contained in:
@@ -0,0 +1 @@
|
||||
.8448951187990853
|
||||
@@ -0,0 +1,183 @@
|
||||
#!/usr/bin/env python3
|
||||
import os
|
||||
import logging
|
||||
from datetime import datetime, timedelta
|
||||
from time import sleep
|
||||
import pandas as pd
|
||||
from binance import Client
|
||||
from forex_python.converter import CurrencyRates
|
||||
import telegram
|
||||
import schedule
|
||||
|
||||
# Configure logging
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format="%(asctime)s - %(levelname)s - %(message)s",
|
||||
)
|
||||
|
||||
# Environment variables for sensitive information
|
||||
API_KEY = os.getenv("BINANCE_API_KEY")
|
||||
API_SECRET = os.getenv("BINANCE_API_SECRET")
|
||||
BOT_TOKEN = os.getenv("TELEGRAM_BOT_TOKEN")
|
||||
BOT_CHAT_ID = os.getenv("TELEGRAM_CHAT_ID")
|
||||
|
||||
# Constants
|
||||
MAX_TRADES = 5
|
||||
RESET_STAKE_AMOUNT = 10 # minutes
|
||||
DATA_DIR = "data"
|
||||
|
||||
# Ensure data directory exists
|
||||
os.makedirs(DATA_DIR, exist_ok=True)
|
||||
|
||||
|
||||
def telegram_send_message(bot_token, bot_chat_id, message):
|
||||
"""
|
||||
Send a message via Telegram bot.
|
||||
"""
|
||||
try:
|
||||
bot = telegram.Bot(token=bot_token)
|
||||
bot.send_message(chat_id=bot_chat_id, text=message)
|
||||
except Exception as e:
|
||||
logging.error(f"Failed to send Telegram message: {e}")
|
||||
|
||||
|
||||
def update_df(gbp, usd, btc, exchange_rate):
|
||||
"""
|
||||
Update the HDF5 file with new balance data.
|
||||
"""
|
||||
try:
|
||||
file_path = os.path.join(DATA_DIR, "balances.h5")
|
||||
time_now = pd.to_datetime(datetime.now().replace(microsecond=0))
|
||||
new_data = pd.DataFrame({
|
||||
"date_time": [time_now],
|
||||
"£": [gbp],
|
||||
"$": [usd],
|
||||
"BTC": [btc],
|
||||
"Ex-rate": [exchange_rate],
|
||||
})
|
||||
|
||||
with pd.HDFStore(file_path) as store:
|
||||
if "df" in store:
|
||||
df = store["df"]
|
||||
df = pd.concat([df, new_data]).drop_duplicates(subset="date_time", keep="first")
|
||||
else:
|
||||
df = new_data.set_index("date_time")
|
||||
store["df"] = df
|
||||
|
||||
logging.info("Updated DataFrame successfully.")
|
||||
|
||||
except Exception as e:
|
||||
logging.error(f"Could not update DataFrame: {e}")
|
||||
telegram_send_message(BOT_TOKEN, BOT_CHAT_ID, "Could not update DataFrame.")
|
||||
|
||||
|
||||
def trim_df():
|
||||
"""
|
||||
Trim the DataFrame to the last 24 hours.
|
||||
"""
|
||||
try:
|
||||
file_path = os.path.join(DATA_DIR, "balances.h5")
|
||||
cut_before = datetime.now() - timedelta(hours=25)
|
||||
|
||||
with pd.HDFStore(file_path) as store:
|
||||
if "df" in store:
|
||||
df = store["df"]
|
||||
df = df[df.index >= cut_before]
|
||||
store["df"] = df
|
||||
|
||||
logging.info("Trimmed DataFrame to the last 24 hours.")
|
||||
except Exception as e:
|
||||
logging.error(f"Could not trim DataFrame: {e}")
|
||||
telegram_send_message(BOT_TOKEN, BOT_CHAT_ID, "Could not trim DataFrame.")
|
||||
|
||||
|
||||
def update_exchange_rate():
|
||||
"""
|
||||
Fetch the latest USD to GBP exchange rate and store it.
|
||||
"""
|
||||
cr = CurrencyRates()
|
||||
file_path = os.path.join(DATA_DIR, "USDGBP_exchange_rate.txt")
|
||||
|
||||
try:
|
||||
exchange_rate = cr.get_rate("USD", "GBP")
|
||||
with open(file_path, "w") as f:
|
||||
f.write(str(exchange_rate))
|
||||
logging.info("Updated USD to GBP exchange rate.")
|
||||
except Exception as e:
|
||||
logging.error(f"Could not update exchange rate: {e}")
|
||||
telegram_send_message(BOT_TOKEN, BOT_CHAT_ID, "Could not update exchange rate.")
|
||||
|
||||
|
||||
def convert_usd_to_gbp(usd):
|
||||
"""
|
||||
Convert USD to GBP using the stored exchange rate.
|
||||
"""
|
||||
file_path = os.path.join(DATA_DIR, "USDGBP_exchange_rate.txt")
|
||||
|
||||
try:
|
||||
with open(file_path, "r") as f:
|
||||
exchange_rate = float(f.read())
|
||||
gbp = usd * exchange_rate
|
||||
return gbp, exchange_rate
|
||||
except Exception as e:
|
||||
logging.error(f"Could not convert USD to GBP: {e}")
|
||||
return usd, 1.0 # Fallback to 1:1 conversion
|
||||
|
||||
|
||||
def get_balance():
|
||||
"""
|
||||
Retrieve account balances from Binance and update the stake amount.
|
||||
"""
|
||||
try:
|
||||
client = Client(API_KEY, API_SECRET)
|
||||
account_info = client.get_account()
|
||||
balances = account_info["balances"]
|
||||
|
||||
usdt = 0.0
|
||||
for balance in balances:
|
||||
asset = balance["asset"]
|
||||
free = float(balance["free"])
|
||||
locked = float(balance["locked"])
|
||||
total = free + locked
|
||||
|
||||
if total > 0:
|
||||
if asset == "USDT":
|
||||
usdt += total
|
||||
else:
|
||||
try:
|
||||
price = float(client.get_symbol_ticker(symbol=f"{asset}USDT")["price"])
|
||||
usdt += total * price
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
btc_price = float(client.get_symbol_ticker(symbol="BTCUSDT")["price"])
|
||||
btc = usdt / btc_price
|
||||
gbp, exchange_rate = convert_usd_to_gbp(usdt)
|
||||
stake_amount = round(usdt / MAX_TRADES)
|
||||
|
||||
with open(os.path.join(DATA_DIR, "stake_amount.txt"), "w") as f:
|
||||
f.write(str(stake_amount))
|
||||
|
||||
update_df(gbp, usdt, btc, exchange_rate)
|
||||
except Exception as e:
|
||||
logging.error(f"Could not fetch balances: {e}")
|
||||
telegram_send_message(BOT_TOKEN, BOT_CHAT_ID, "Could not fetch Binance balances.")
|
||||
|
||||
|
||||
def run_code():
|
||||
"""
|
||||
Main function to schedule tasks and run the bot.
|
||||
"""
|
||||
update_exchange_rate()
|
||||
get_balance()
|
||||
schedule.every(RESET_STAKE_AMOUNT).minutes.do(get_balance)
|
||||
schedule.every().day.at("11:45").do(update_exchange_rate)
|
||||
schedule.every(4).hours.do(trim_df)
|
||||
|
||||
while True:
|
||||
schedule.run_pending()
|
||||
sleep(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
run_code()
|
||||
@@ -0,0 +1,263 @@
|
||||
#!/usr/bin/env python3
|
||||
import os
|
||||
import time
|
||||
import shutil
|
||||
import warnings
|
||||
import pandas as pd
|
||||
import matplotlib.pyplot as plt # pip install matplotlib
|
||||
import matplotlib.dates as mdates
|
||||
from datetime import datetime, timedelta, date
|
||||
import telegram
|
||||
import schedule # pip install schedule
|
||||
|
||||
warnings.simplefilter(action='ignore', category=FutureWarning)
|
||||
|
||||
# Constants
|
||||
LONG_PLOT_DAYS = -1 # 60 # -1 all days in df
|
||||
LONG_PLOT_CURRENCY = '£'
|
||||
PLOT_CURRENCY = '$'
|
||||
|
||||
# Environment variables for sensitive information
|
||||
API_KEY = os.getenv("BINANCE_API_KEY")
|
||||
API_SECRET = os.getenv("BINANCE_API_SECRET")
|
||||
BOT_TOKEN = os.getenv("TELEGRAM_BOT_TOKEN")
|
||||
BOT_CHAT_ID = os.getenv("TELEGRAM_CHAT_ID")
|
||||
|
||||
|
||||
date_today = date.today()
|
||||
TODAY = date_today.strftime("%Y_%m_%d")
|
||||
|
||||
|
||||
def telegram_send_image(bot_token, bot_chat_id, image_path):
|
||||
"""Send an image to the specified Telegram chat."""
|
||||
bot = telegram.Bot(token=bot_token)
|
||||
with open(image_path, 'rb') as photo:
|
||||
bot.send_photo(chat_id=bot_chat_id, photo=photo)
|
||||
return ()
|
||||
|
||||
|
||||
def telegram_send_message(bot_token, bot_chat_id, message):
|
||||
"""Send a message to the specified Telegram chat."""
|
||||
bot = telegram.Bot(token=bot_token)
|
||||
bot.send_message(chat_id=bot_chat_id, text=message)
|
||||
return ()
|
||||
|
||||
|
||||
def plot_and_send_image(df, currency, plot_title, file_name):
|
||||
"""Generate plot and send it as an image to Telegram."""
|
||||
plt.rcParams.update({'font.size': 14, 'font.family': 'STIXGeneral', 'mathtext.fontset': 'stix'})
|
||||
fig, axs = plt.subplots(figsize=(7, 4))
|
||||
axs.xaxis.set_major_formatter(mdates.DateFormatter("%d %b"))
|
||||
df[currency].plot.line(ax=axs, color="darkgreen", linewidth=1.50)
|
||||
delta_y = int(df[currency].max()) - int(df[currency].min())
|
||||
y_min = int(df[currency].min()) - (delta_y * 0.05)
|
||||
y_max = int(df[currency].max()) + (delta_y * 0.05)
|
||||
x_max = datetime.now()
|
||||
x_min = datetime.now() - timedelta(days=len(df))
|
||||
axs.set_title(plot_title)
|
||||
axs.set_ylim(y_min, y_max)
|
||||
axs.set_xlim(x_min, x_max)
|
||||
axs.set_ylabel("")
|
||||
axs.set_xlabel("")
|
||||
axs.grid(color='grey', alpha=0.5, linestyle='dashed', linewidth=0.5)
|
||||
axs.yaxis.set_major_formatter(f"{currency} {{x:1.0f}}")
|
||||
|
||||
plt.savefig(file_name)
|
||||
plt.cla()
|
||||
plt.close(fig)
|
||||
|
||||
# Send image to Telegram
|
||||
telegram_send_image(BOT_TOKEN, BOT_CHAT_ID, file_name)
|
||||
return ()
|
||||
|
||||
|
||||
def plot_long(period=LONG_PLOT_DAYS, currency=LONG_PLOT_CURRENCY):
|
||||
"""Plot long-term data."""
|
||||
try:
|
||||
if os.path.exists('balances_24h.h5'):
|
||||
balances_24h = pd.HDFStore('balances_24h.h5')
|
||||
df = balances_24h['df_24h'].iloc[1:, :]
|
||||
balances_24h.close()
|
||||
if period == -1:
|
||||
no_of_days = len(df)
|
||||
else:
|
||||
no_of_days = period
|
||||
df = df.tail(no_of_days)
|
||||
plot_and_send_image(df, currency, f"{no_of_days} days plot", "plot_long.png")
|
||||
else:
|
||||
message = "No balances_24h.h5 file"
|
||||
telegram_send_message(BOT_TOKEN, BOT_CHAT_ID, message)
|
||||
except Exception:
|
||||
message = "Could not generate long plot"
|
||||
telegram_send_message(BOT_TOKEN, BOT_CHAT_ID, message)
|
||||
return ()
|
||||
|
||||
|
||||
def plot_30days(currency=PLOT_CURRENCY):
|
||||
"""Plot 30 days data."""
|
||||
try:
|
||||
if os.path.exists('balances_4h.h5'):
|
||||
balances_4h = pd.HDFStore('balances_4h.h5')
|
||||
df = balances_4h['df_4h'].iloc[1:, :]
|
||||
balances_4h.close()
|
||||
df = df.tail(180)
|
||||
plot_and_send_image(df, currency, "30 Day Balances", "30_days.png")
|
||||
else:
|
||||
message = "No balances_4h.h5 file"
|
||||
telegram_send_message(BOT_TOKEN, BOT_CHAT_ID, message)
|
||||
except Exception:
|
||||
message = "Could not generate 30 day plot"
|
||||
telegram_send_message(BOT_TOKEN, BOT_CHAT_ID, message)
|
||||
return ()
|
||||
|
||||
|
||||
def plot_7days(currency=PLOT_CURRENCY):
|
||||
"""Plot 7 days data."""
|
||||
try:
|
||||
if os.path.exists('balances_1h.h5'):
|
||||
balances_1h = pd.HDFStore('balances_1h.h5')
|
||||
df = balances_1h['df_1h']
|
||||
end_date = datetime.now().replace(microsecond=0)
|
||||
cut_before_date = end_date - timedelta(days=7)
|
||||
df = df.loc[df.index >= cut_before_date]
|
||||
plot_and_send_image(df, currency, "7 Day Balances", "7_days.png")
|
||||
else:
|
||||
message = "No balances_1h.h5 file"
|
||||
telegram_send_message(BOT_TOKEN, BOT_CHAT_ID, message)
|
||||
except Exception:
|
||||
message = "Could not generate 7 day plot"
|
||||
telegram_send_message(BOT_TOKEN, BOT_CHAT_ID, message)
|
||||
return ()
|
||||
|
||||
|
||||
def plot_24h(currency=PLOT_CURRENCY):
|
||||
"""Plot 24 hours data."""
|
||||
try:
|
||||
if os.path.exists('balances.h5'):
|
||||
balances = pd.HDFStore('balances.h5')
|
||||
df = balances['df'].iloc[1:, :]
|
||||
df['date_time'] = pd.to_datetime(df['date_time'])
|
||||
balances.close()
|
||||
df = df.set_index('date_time')
|
||||
plot_and_send_image(df, currency, TODAY, "24_hour.png")
|
||||
else:
|
||||
message = "No balances.h5 file"
|
||||
telegram_send_message(BOT_TOKEN, BOT_CHAT_ID, message)
|
||||
except Exception:
|
||||
message = "Could not generate 24h plot"
|
||||
telegram_send_message(BOT_TOKEN, BOT_CHAT_ID, message)
|
||||
return ()
|
||||
|
||||
|
||||
def send_plots():
|
||||
"""Send all generated plots to Telegram."""
|
||||
try:
|
||||
balances = pd.HDFStore('balances.h5')
|
||||
df = balances['df']
|
||||
balances.close()
|
||||
GBP = df['£'].iloc[-1]
|
||||
USDT = df['$'].iloc[-1]
|
||||
BTC = df['BTC'].iloc[-1]
|
||||
|
||||
message = f"Balance:\n GBP £ {round(GBP, 2)}\n USD $ {round(USDT, 2)}\n BTC {round(BTC, 6)}"
|
||||
telegram_send_message(BOT_TOKEN, BOT_CHAT_ID, message)
|
||||
|
||||
# Send all plots
|
||||
for file_name in ["plot_long.png", "30_days.png", "7_days.png", "24_hour.png"]:
|
||||
if os.path.exists(file_name):
|
||||
telegram_send_image(BOT_TOKEN, BOT_CHAT_ID, file_name)
|
||||
else:
|
||||
telegram_send_message(BOT_TOKEN, BOT_CHAT_ID, f"Could not find {file_name}")
|
||||
|
||||
print(f"{datetime.now().replace(microsecond=0)} - Sent plots to Telegram.")
|
||||
except Exception:
|
||||
message = "Could not send plots."
|
||||
telegram_send_message(BOT_TOKEN, BOT_CHAT_ID, message)
|
||||
return ()
|
||||
|
||||
|
||||
def resample_data():
|
||||
"""Resample data to 1h, 4h, and 24h."""
|
||||
try:
|
||||
if not os.path.exists("balances_1h.h5"):
|
||||
balances = pd.HDFStore('balances.h5')
|
||||
df = balances['df']
|
||||
df['date_time'] = pd.to_datetime(df['date_time'])
|
||||
df = df.set_index('date_time')
|
||||
balances.close()
|
||||
|
||||
# Resample to 1h
|
||||
data_1h = df.resample("H").mean()
|
||||
balances_1h = pd.HDFStore('balances_1h.h5')
|
||||
balances_1h['df_1h'] = data_1h
|
||||
balances_1h.close()
|
||||
|
||||
if not os.path.exists("balances_4h.h5"):
|
||||
balances_1h = pd.HDFStore('balances_1h.h5')
|
||||
df_1h = balances_1h['df_1h']
|
||||
balances_1h.close()
|
||||
|
||||
# Resample to 4h
|
||||
data_4h = df_1h.resample("4H").mean()
|
||||
balances_4h = pd.HDFStore('balances_4h.h5')
|
||||
balances_4h['df_4h'] = data_4h
|
||||
balances_4h.close()
|
||||
|
||||
if not os.path.exists("balances_24h.h5"):
|
||||
balances_4h = pd.HDFStore('balances_4h.h5')
|
||||
df_4h = balances_4h['df_4h']
|
||||
balances_4h.close()
|
||||
|
||||
# Resample to 24h
|
||||
data_24h = df_4h.resample("24H").mean()
|
||||
balances_24h = pd.HDFStore('balances_24h.h5')
|
||||
balances_24h['df_24h'] = data_24h
|
||||
balances_24h.close()
|
||||
|
||||
except Exception:
|
||||
message = "Error in resampling data"
|
||||
telegram_send_message(BOT_TOKEN, BOT_CHAT_ID, message)
|
||||
return ()
|
||||
|
||||
|
||||
def delete_old_files():
|
||||
"""Delete old files in the directory."""
|
||||
try:
|
||||
directory = "path_to_your_directory"
|
||||
for file_name in os.listdir(directory):
|
||||
file_path = os.path.join(directory, file_name)
|
||||
if os.path.getmtime(file_path) < time.time() - 7 * 86400:
|
||||
os.remove(file_path)
|
||||
except Exception:
|
||||
message = "Error in deleting old files"
|
||||
telegram_send_message(BOT_TOKEN, BOT_CHAT_ID, message)
|
||||
return ()
|
||||
|
||||
|
||||
def archive_data():
|
||||
"""Archive old data to a zip file."""
|
||||
try:
|
||||
archive_name = f"archive_data_{TODAY}.zip"
|
||||
if not os.path.exists('archive_data'):
|
||||
os.makedirs('archive_data')
|
||||
shutil.make_archive(f'archive_data/{archive_name}', 'zip', 'path_to_your_directory')
|
||||
except Exception:
|
||||
message = "Error in archiving data"
|
||||
telegram_send_message(BOT_TOKEN, BOT_CHAT_ID, message)
|
||||
return ()
|
||||
|
||||
|
||||
# Scheduling tasks
|
||||
schedule.every().day.at("00:00").do(archive_data)
|
||||
schedule.every().day.at("01:00").do(delete_old_files)
|
||||
schedule.every().day.at("02:00").do(resample_data)
|
||||
schedule.every().day.at("02:30").do(plot_long)
|
||||
schedule.every().day.at("03:00").do(plot_30days)
|
||||
schedule.every().day.at("03:30").do(plot_7days)
|
||||
schedule.every().day.at("04:00").do(plot_24h)
|
||||
schedule.every().day.at("05:00").do(send_plots)
|
||||
|
||||
# Main loop
|
||||
while True:
|
||||
schedule.run_pending()
|
||||
time.sleep(1)
|
||||
@@ -0,0 +1 @@
|
||||
4164
|
||||
Reference in New Issue
Block a user