-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbasic_bot.py
More file actions
144 lines (119 loc) · 4.61 KB
/
basic_bot.py
File metadata and controls
144 lines (119 loc) · 4.61 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
import sys
import time
import logging
from binance import Client
from binance.exceptions import BinanceAPIException, BinanceOrderException
# =========================
# LOGGING CONFIGURATION
# =========================
logging.basicConfig(
filename="bot.log",
level=logging.INFO,
format="%(asctime)s | %(levelname)s | %(message)s"
)
# =========================
# BASIC BINANCE FUTURES BOT
# =========================
class BasicBot:
def __init__(self, api_key, api_secret, testnet=True):
self.client = Client(api_key, api_secret)
if testnet:
self.client.FUTURES_URL = "https://testnet.binancefuture.com"
logging.info("Bot initialized (Testnet=%s)", testnet)
def validate_inputs(self, symbol, side, order_type, quantity, price=None):
if not symbol.endswith("USDT"):
raise ValueError("Symbol must be USDT-M futures (e.g., BTCUSDT)")
if side not in ["BUY", "SELL"]:
raise ValueError("Side must be BUY or SELL")
if order_type not in ["MARKET", "LIMIT"]:
raise ValueError("Order type must be MARKET or LIMIT")
if quantity <= 0:
raise ValueError("Quantity must be greater than zero")
if order_type == "LIMIT" and (price is None or price <= 0):
raise ValueError("Limit orders require a valid price")
# ---------------------
# MARKET ORDER
# ---------------------
def place_market_order(self, symbol, side, quantity):
try:
order = self.client.futures_create_order(
symbol=symbol,
side=side,
type="MARKET",
quantity=quantity,
newOrderRespType="RESULT"
)
logging.info("Market Order Placed: %s", order)
# Retry fetching order details if needed
order_id = order.get("orderId")
if order_id:
for _ in range(3): # 3 attempts
try:
order_details = self.client.futures_get_order(symbol=symbol, orderId=order_id)
return order_details
except Exception:
time.sleep(0.5) # wait half a second
# fallback to original order if get_order fails
return order
else:
return order
except (BinanceAPIException, BinanceOrderException) as e:
logging.error("Market Order Failed: %s", e)
raise
# ---------------------
# LIMIT ORDER
# ---------------------
def place_limit_order(self, symbol, side, quantity, price):
try:
order = self.client.futures_create_order(
symbol=symbol,
side=side,
type="LIMIT",
timeInForce="GTC",
quantity=quantity,
price=price,
newOrderRespType="RESULT"
)
logging.info("Limit Order Placed: %s", order)
return order
except (BinanceAPIException, BinanceOrderException) as e:
logging.error("Limit Order Failed: %s", e)
raise
# =========================
# CLI ENTRY POINT
# =========================
def main():
if len(sys.argv) < 5:
print("Usage:")
print("py basic_bot.py SYMBOL SIDE ORDER_TYPE QUANTITY [PRICE]")
sys.exit(1)
symbol = sys.argv[1].upper()
side = sys.argv[2].upper()
order_type = sys.argv[3].upper()
quantity = float(sys.argv[4])
price = float(sys.argv[5]) if len(sys.argv) == 6 else None
# 🔐 INSERT YOUR TESTNET KEYS HERE
API_KEY = "PASTE_YOUR_TESTNET_API_KEY"
API_SECRET = "PASTE_YOUR_TESTNET_API_SECRET"
bot = BasicBot(API_KEY, API_SECRET, testnet=True)
try:
bot.validate_inputs(symbol, side, order_type, quantity, price)
if order_type == "MARKET":
order_details = bot.place_market_order(symbol, side, quantity)
else:
order_details = bot.place_limit_order(symbol, side, quantity, price)
print("ORDER SUCCESS")
# Display order details if available
if order_details:
print("Order ID:", order_details.get("orderId"))
print("Symbol:", order_details.get("symbol"))
print("Status:", order_details.get("status"))
print("Side:", order_details.get("side"))
print("Type:", order_details.get("type"))
else:
print("Order placed, but unable to fetch order details")
except Exception as e:
print("ERROR:", str(e))
logging.error("Execution Error: %s", e)
if __name__ == "__main__":
main()