Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save Br4ndonP0nce/53b089d946750ac529452fab063d8ebb to your computer and use it in GitHub Desktop.
Save Br4ndonP0nce/53b089d946750ac529452fab063d8ebb to your computer and use it in GitHub Desktop.
TradingBot Binance runs asynchronously a websocket to read latest data price for the pair BTCUSDT
import os
import asyncio
import math
from binance import AsyncClient, BinanceSocketManager
from dotenv import load_dotenv
from datetime import datetime
import time
# Load environment variables from .env file
load_dotenv()
# Fetch API key and secret from environment variables
api_key = os.getenv('BINANCE_API_KEY')
api_secret = os.getenv('BINANCE_API_SECRET')
# Ensure API key and secret are set
if not api_key or api_secret is None:
raise ValueError("Please set the BINANCE_API_KEY and BINANCE_API_SECRET environment variables in the .env file.")
# Global variables to hold the latest market price and balances
latest_price = None
usdt_balance = 0.0
btc_balance = 0.0
min_qty = 0.0
min_notional = 0.0
step_size = 0.0
entry_price = 0.0
entry_quantity = 0.0
initial_btc_balance = 0.0
initial_usdt_balance = 0.0
last_update = None
async def handle_socket_message(msg):
global latest_price
if msg['e'] == 'error':
print(f"Error: {msg}")
else:
latest_price = float(msg['p'])
print(f"Updated latest price: {latest_price:.2f} USD") # Debugging statement
async def get_account_info(client):
global usdt_balance, btc_balance, initial_btc_balance, initial_usdt_balance
account_info = await client.get_account()
balances = account_info['balances']
for balance in balances:
if balance['asset'] == 'USDT':
usdt_balance = float(balance['free'])
if initial_usdt_balance == 0.0:
initial_usdt_balance = usdt_balance
if balance['asset'] == 'BTC':
btc_balance = float(balance['free'])
if initial_btc_balance == 0.0:
initial_btc_balance = btc_balance
async def place_order(client, symbol, side, order_type, quantity, price=None):
if order_type == 'MARKET':
order = await client.order_market(
symbol=symbol,
side=side,
quantity=quantity
)
elif order_type == 'LIMIT':
order = await client.order_limit(
symbol=symbol,
side=side,
timeInForce='GTC',
quantity=quantity,
price=price
)
return order
async def check_open_orders(client, symbol):
orders = await client.get_open_orders(symbol=symbol)
if orders:
print(f"Open Orders for {symbol}:")
for order in orders:
print(f" Order ID: {order['orderId']}, Status: {order['status']}, Price: {order['price']}, Quantity: {order['origQty']}")
else:
print(f"No open orders for {symbol}.")
async def check_completed_orders(client, symbol):
orders = await client.get_all_orders(symbol=symbol)
filled_orders = [order for order in orders if order['status'] == 'FILLED']
if filled_orders:
print(f"Order History for {symbol}:")
for order in filled_orders:
order_time = datetime.fromtimestamp(order['time'] / 1000).strftime('%Y-%m-%d %H:%M:%S')
print(f" Order ID: {order['orderId']}, Side: {order['side']}, Price: {order['price']}, Quantity: {order['origQty']}, Time: {order_time}")
else:
print(f"No completed orders for {symbol}.")
def is_socket_active():
global last_update
if last_update is None:
return False
current_time = time.time()
# Check if the last update was within the last 30 seconds
return (current_time - last_update) < 30
async def start_socket(client, symbol):
global latest_price
bsm = BinanceSocketManager(client)
ts = bsm.trade_socket(symbol)
async with ts as tscm:
while True:
res = await tscm.recv()
await handle_socket_message(res)
async def get_min_trade_info(client, symbol):
global min_qty, min_notional, step_size
info = await client.get_symbol_info(symbol)
for filter in info['filters']:
if filter['filterType'] == 'LOT_SIZE':
min_qty = float(filter['minQty'])
step_size = float(filter['stepSize'])
if filter['filterType'] == 'MIN_NOTIONAL':
min_notional = float(filter['minNotional'])
print(f"min_qty: {min_qty}, min_notional: {min_notional}, step_size: {step_size}")
def adjust_to_step_size(quantity, step_size):
return math.floor(quantity / step_size) * step_size
def round_step_size(quantity, step_size):
precision = int(round(-math.log(step_size, 10), 0))
return round(quantity, precision)
async def scalping_strategy(client, symbol, usd_amount, profit_threshold, loss_threshold):
global latest_price, usdt_balance, btc_balance, min_qty, min_notional, step_size, entry_price, entry_quantity
# Define the size of buy orders in USD
buy_amount_usd = usd_amount
while True:
if latest_price is None:
print("Waiting for price update...")
await asyncio.sleep(1)
continue
# Only calculate the current worth and PNL if we have an entry
if entry_quantity > 0:
current_worth = entry_quantity * latest_price
pnl = current_worth - buy_amount_usd
else:
current_worth = 0
pnl = 0
# Print current status
print(f"Live BTC Price: {latest_price:.2f} USD")
print(f"USDT Balance: {usdt_balance:.2f}")
print(f"BTC Balance: {btc_balance:.6f}")
print(f"Entry Quantity: {entry_quantity:.6f} BTC")
print(f"Entry Price: {entry_price:.2f} USD")
print(f"Current Worth: {current_worth:.2f} USD")
print(f"PNL: {pnl:.2f} USD")
# Check if we have enough USDT to place a buy order
if usdt_balance >= buy_amount_usd and entry_quantity == 0:
buy_quantity = buy_amount_usd / latest_price
buy_quantity = adjust_to_step_size(buy_quantity, step_size)
buy_quantity = round_step_size(buy_quantity, step_size)
# Ensure buy quantity meets the minimum lot size and notional value
if buy_quantity >= min_qty and (buy_quantity * latest_price) >= min_notional:
# Place a buy order
order = await place_order(client, symbol, 'BUY', 'MARKET', buy_quantity)
print("Buy Order Result:")
for key, value in order.items():
print(f" {key}: {value}")
# Store the entry price and quantity
entry_price = latest_price
entry_quantity = buy_quantity
print("Entry price:", entry_price, "\nEntry quantity:", entry_quantity)
# Check for open orders after placing the buy order
# await check_open_orders(client, symbol)
# Check for completed orders after placing the buy order
#await check_completed_orders(client, symbol)
# Calculate the target sell price and stop loss price based on the entry amount in USD
target_sell_value = buy_amount_usd * (1 + profit_threshold / 100)
stop_loss_value = buy_amount_usd * (1 - loss_threshold / 100)
print("Target sell:", target_sell_value, "\nStop loss:", stop_loss_value)
while entry_quantity > 0:
if latest_price is None:
await asyncio.sleep(1)
continue
if not is_socket_active():
print("Socket inactive! No updates received recently.")
# Add logic to handle socket inactivity (e.g., restart the socket)
# For simplicity, we just print a message here
await asyncio.sleep(5) # Wait before rechecking
continue
else:
print("wu socket good")
current_worth = entry_quantity * latest_price
pnl = current_worth - buy_amount_usd
# Debugging output for monitoring phase
print(f"Monitoring: latest_price={latest_price}, target_sell_value={target_sell_value}, stop_loss_value={stop_loss_value}, current_worth={current_worth}")
# Check if the current worth has reached the target sell value or stop loss value
if current_worth >= target_sell_value or current_worth <= stop_loss_value:
print("Placing sell order")
# Place a sell order
sell_quantity = entry_quantity
sell_quantity = adjust_to_step_size(sell_quantity, step_size)
sell_quantity = round_step_size(sell_quantity, step_size)
order = await place_order(client, symbol, 'SELL', 'MARKET', sell_quantity)
print("Sell Order Result:")
for key, value in order.items():
print(f" {key}: {value}")
# Reset entry price and quantity
entry_price = 0
entry_quantity = 0
# Update balances after selling
await get_account_info(client)
# Check for open orders after placing the sell order
await check_open_orders(client, symbol)
# Check for completed orders after placing the sell order
await check_completed_orders(client, symbol)
break
# Update balances periodically even if no trades are made
await get_account_info(client)
await asyncio.sleep(1) # Adjust the update interval as needed
async def main():
global usdt_balance, btc_balance
# Initialize the client with the Testnet parameter
client = await AsyncClient.create(api_key, api_secret, testnet=True)
# Get initial account information
await get_account_info(client)
# Get minimum trade information for the symbol
await get_min_trade_info(client,"BTCUSDT")
# Get minimum trade information for the symbol
await get_min_trade_info(client, 'BTCUSDT')
# Start the WebSocket connection in a background task
asyncio.create_task(start_socket(client, 'BTCUSDT'))
# Define strategy parameters
usd_amount = 10 # Buy order size in USD
profit_threshold = 1 # Profit threshold in percentage
loss_threshold = 20 # Loss threshold in percentage
# Start the scalping strategy
await scalping_strategy(client, 'BTCUSDT', usd_amount, profit_threshold, loss_threshold)
await client.close_connection()
if __name__ == "__main__":
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment