I’m building a Discord bot that uses the Binance API to fetch the latest price of a cryptocurrency. However, I’m encountering an issue where the price returned by my bot is inconsistent. Specifically, the price varies based on the timeframe used to fetch historical data, instead of consistently returning the actual live price.
Here’s a summary of what I’m doing:
-
Fetching Historical Data: Using
get_realtime_data()
to fetch OHLCV data for a given symbol and interval. -
Fetching Latest Price: Using
get_latest_price()
to fetch the current live price.
Expected Behaviour
The bot should return the current live price of the cryptocurrency, regardless of the timeframe specified.
The Observed Behaviour
The bot returns different prices depending on the timeframe, and these prices do not match the actual live price from Binance.
# Data fetching methods in my data_collection.py
from binance.client import Client
import pandas as pd
client = Client(api_key, api_secret)
def get_realtime_data(symbol, interval):
# Fetch historical OHLCV data
klines = client.get_klines(symbol=symbol, interval=interval, limit=100)
# Processing data into DataFrame
...
def get_latest_price(symbol):
# Fetch the latest price
ticker = client.get_symbol_ticker(symbol=symbol)
return float(ticker['price'])
# Commands in main.py
import discord
import asyncio
import os
import time
import mplfinance as mpf
from discord.ext import commands
from dotenv import load_dotenv
from Data.data_collection import get_realtime_data
from patterns.mainPatterns.signal_generator import SignalGenerator
# Load environment variables from .env file
load_dotenv()
# Retrieve Binance API keys and Discord token from environment variables
api_key = os.getenv('BINANCE_API_KEY')
api_secret = os.getenv('BINANCE_API_SECRET')
discord_token = os.getenv('DISCORD_TOKEN')
if not api_key or not api_secret or not discord_token:
raise ValueError("One or more environment variables are missing.")
intents = discord.Intents.default()
intents.message_content = True
bot = commands.Bot(command_prefix='!', intents=intents)
@bot.event
async def on_ready():
print(f'We have logged in as {bot.user}')
@bot.command(name='control')
async def control_signal(ctx, symbol: str, interval: str, time_limit: str, duration: str):
timeout = time.time() + 60 * float(time_limit) # minutes till timeout
signal_generator = SignalGenerator(symbol, interval)
while True:
if time.time() > timeout:
await ctx.send("Time has elapsed for updates")
break
try:
current_data = get_realtime_data(symbol, interval)
signals = signal_generator.generate_signals(current_data)
response = "n".join(signals) if signals else "No signals found."
await ctx.send(response)
except Exception as e:
await ctx.send(f"Error generating signals: {e}")
await asyncio.sleep(int(duration)) # use asyncio.sleep for non-blocking sleep
@bot.command(name='timer')
async def timer_signal(ctx, symbol: str, interval: str, time_limit: str):
timeout = time.time() + 60 * float(time_limit)
signal_generator = SignalGenerator(symbol, interval)
while True:
if time.time() > timeout:
await ctx.send("Time has elapsed for updates")
break
try:
current_data = get_realtime_data(symbol, interval)
signals = signal_generator.generate_signals(current_data)
response = "n".join(signals) if signals else "No signals found."
await ctx.send(response)
except Exception as e:
await ctx.send(f"Error generating signals: {e}")
await asyncio.sleep(10) # refresh every 10 seconds
@bot.command(name='signal')
async def single_signal(ctx, symbol: str, interval: str):
signal_generator = SignalGenerator(symbol, interval)
try:
current_data = get_realtime_data(symbol, interval)
signals = signal_generator.generate_signals(current_data)
response = "n".join(signals) if signals else "No signals found."
await ctx.send(response)
except Exception as e:
await ctx.send(f"Error generating signals: {e}")
@bot.command(name='generate')
async def generate_graph(ctx, symbol: str, interval: str):
signal_generator = SignalGenerator(symbol, interval)
try:
current_data = get_realtime_data(symbol, interval)
signals = signal_generator.generate_signals(current_data)
response = "n".join(signals) if signals else "No signals found."
await ctx.send(response)
# This makes sure the data has the correct columns for mplfinance
required_columns = {'open', 'high', 'low', 'close', 'volume'}
if not required_columns.issubset(current_data.columns):
raise ValueError(f"Data is missing one or more required columns: {required_columns}")
mpf.plot(current_data, type='candle', style='charles', volume=True, savefig='pattern.png')
if os.path.exists('pattern.png'):
await ctx.send(file=discord.File('pattern.png'))
else:
await ctx.send("No pattern detected or unable to generate plot.")
except Exception as e:
await ctx.send(f"Error generating graph: {e}")
# Run the bot
bot.run(discord_token)