Giriş
Binance, dünyanın en büyük kripto para borsalarından biri olarak günlük milyarlarca dolarlık işlem hacmine sahiptir. Python ile Binance API entegrasyonu, otomatik trading botları geliştirmek, portföy yönetimi yapmak ve gerçek zamanlı piyasa verilerini analiz etmek isteyen geliştiriciler için güçlü bir araçtır.
Bu kapsamlı rehberde, Binance API’sini Python ile nasıl kullanacağınızı sıfırdan öğreneceksiniz. REST API ile temel işlemler yapmayı, WebSocket ile gerçek zamanlı veri akışını dinlemeyi, order placement stratejilerini ve güvenli API key yönetimini detaylıca ele alacağız. Ayrıca, production-ready trading botları geliştirmek için gereken best practice’leri ve error handling mekanizmalarını da göreceğiz.
Şekil 1: Kripto trading sistemi mimarisi genel görünümü
Binance API’ye Giriş
API Türleri
Binance üç farklı API türü sunar:
- REST API: HTTP istekleri ile trading, account bilgileri ve market data için kullanılır
- WebSocket API: Gerçek zamanlı veri akışları (fiyatlar, order book, trades)
- WebSocket Streams: Market data ve user data stream’leri
API Limitleri
Binance, API kullanımında belirli limitler koyar:
- Request Weight: Her endpoint’in bir weight değeri var (1-10 arası)
- Raw Requests: Dakikada maksimum 1200 raw request
- Order Limits: 10 saniyede 100 order, günde 200.000 order
- WebSocket: Açık connection sayısı ve subscription limitleri
Güvenlik Seviyeleri
- Public Endpoints: API key gerektirmez (market data)
- TRADE Endpoints: API key + SECRET key gerektirir (trading işlemleri)
- USER_DATA Endpoints: API key + SECRET key gerektirir (account bilgileri)
- MARGIN Endpoints: Margin trading için özel izinler
Kurulum ve Başlangıç
Gerekli Kütüphanelerin Kurulumu
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| # Binance API wrapper'ı
pip install python-binance
# Alternatif: ccxt (multiple exchange support)
pip install ccxt
# Veri analizi için
pip install pandas numpy
# Async işlemler için
pip install asyncio aiohttp
# WebSocket için
pip install websockets
# Güvenlik için
pip install python-dotenv cryptography
# Logging ve monitoring
pip install loguru
|
API Key Oluşturma
- Binance hesabınıza giriş yapın
- API Management sayfasına gidin
- “Create API” butonuna tıklayın
- API key’i güvenli bir yere kaydedin
- İzinleri yapılandırın:
- Enable Reading
- Enable Spot & Margin Trading
- IP whitelist ekleyin (önerilir)
Güvenli API Key Yönetimi
API key’lerinizi asla public repository’ye eklemeyin! .env dosyasını mutlaka .gitignore’a ekleyin.
1
2
| BINANCE_API_KEY=your_api_key_here
BINANCE_SECRET_KEY=your_secret_key_here
|
1
2
3
4
5
6
7
8
| # Python'dan okuyun
from dotenv import load_dotenv
import os
load_dotenv()
API_KEY = os.getenv('BINANCE_API_KEY')
SECRET_KEY = os.getenv('BINANCE_SECRET_KEY')
|
1
2
3
| .env
*.key
secrets/
|
REST API ile Temel İşlemler
Client Oluşturma
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
| from binance.client import Client
from binance.exceptions import BinanceAPIException
import os
from dotenv import load_dotenv
# Environment variables'ı yükle
load_dotenv()
# Client oluştur
client = Client(
api_key=os.getenv('BINANCE_API_KEY'),
api_secret=os.getenv('BINANCE_SECRET_KEY')
)
# Testnet kullanımı (test için)
# client = Client(
# api_key=os.getenv('TESTNET_API_KEY'),
# api_secret=os.getenv('TESTNET_SECRET_KEY'),
# testnet=True
# )
# Server zamanını kontrol et
def check_server_time():
"""
Binance server zamanını kontrol et
Local time ile sync olması önemli
"""
try:
server_time = client.get_server_time()
print(f"Server Time: {server_time['serverTime']}")
return True
except BinanceAPIException as e:
print(f"Error: {e}")
return False
check_server_time()
|
Market Data Çekme
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
| import pandas as pd
from datetime import datetime, timedelta
def get_ticker_price(symbol='BTCUSDT'):
"""
Belirli bir symbol için güncel fiyatı al
Parameters:
symbol (str): Trading pair (örn: 'BTCUSDT', 'ETHUSDT')
Returns:
dict: Fiyat bilgileri
"""
try:
ticker = client.get_symbol_ticker(symbol=symbol)
print(f"{symbol} Price: ${float(ticker['price']):,.2f}")
return ticker
except BinanceAPIException as e:
print(f"Error getting ticker: {e}")
return None
def get_24h_stats(symbol='BTCUSDT'):
"""
24 saatlik istatistikleri al
"""
try:
stats = client.get_ticker(symbol=symbol)
print(f"\n24h Statistics for {symbol}:")
print(f"High: ${float(stats['highPrice']):,.2f}")
print(f"Low: ${float(stats['lowPrice']):,.2f}")
print(f"Volume: {float(stats['volume']):,.2f}")
print(f"Quote Volume: ${float(stats['quoteVolume']):,.2f}")
print(f"Price Change: {float(stats['priceChangePercent']):.2f}%")
return stats
except BinanceAPIException as e:
print(f"Error: {e}")
return None
# Kullanım
get_ticker_price('BTCUSDT')
get_24h_stats('BTCUSDT')
|
Historical Data (Klines) Çekme
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
| def get_historical_klines(
symbol='BTCUSDT',
interval='1h',
lookback='30 days ago UTC'
):
"""
Historical candlestick data çek
Parameters:
symbol (str): Trading pair
interval (str): Zaman dilimi ('1m', '5m', '15m', '1h', '4h', '1d', etc.)
lookback (str): Ne kadar geriye git
Returns:
pd.DataFrame: OHLCV verisi
"""
try:
# Klines verisi çek
klines = client.get_historical_klines(
symbol,
interval,
lookback
)
# DataFrame'e dönüştür
df = pd.DataFrame(klines, columns=[
'timestamp', 'open', 'high', 'low', 'close', 'volume',
'close_time', 'quote_volume', 'trades',
'taker_buy_base', 'taker_buy_quote', 'ignore'
])
# Veri tiplerini düzenle
df['timestamp'] = pd.to_datetime(df['timestamp'], unit='ms')
df['close_time'] = pd.to_datetime(df['close_time'], unit='ms')
numeric_columns = ['open', 'high', 'low', 'close', 'volume']
df[numeric_columns] = df[numeric_columns].astype(float)
# Sadece gerekli kolonları tut
df = df[['timestamp', 'open', 'high', 'low', 'close', 'volume']]
df.set_index('timestamp', inplace=True)
print(f"\nHistorical data çekildi: {len(df)} kayıt")
print(df.head())
return df
except BinanceAPIException as e:
print(f"Error: {e}")
return None
# Örnek kullanım
btc_data = get_historical_klines('BTCUSDT', '1h', '7 days ago UTC')
eth_data = get_historical_klines('ETHUSDT', '15m', '24 hours ago UTC')
|
Order Book Analizi
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
| def get_order_book(symbol='BTCUSDT', limit=20):
"""
Order book (emir defteri) verisi al
Parameters:
symbol (str): Trading pair
limit (int): Kaç seviye gösterilecek (5, 10, 20, 50, 100, 500, 1000, 5000)
Returns:
dict: Order book verisi
"""
try:
depth = client.get_order_book(symbol=symbol, limit=limit)
# Bid ve ask verilerini DataFrame'e dönüştür
bids_df = pd.DataFrame(depth['bids'], columns=['price', 'quantity'])
asks_df = pd.DataFrame(depth['asks'], columns=['price', 'quantity'])
bids_df = bids_df.astype(float)
asks_df = asks_df.astype(float)
# Kümülatif hacim hesapla
bids_df['cumulative'] = bids_df['quantity'].cumsum()
asks_df['cumulative'] = asks_df['quantity'].cumsum()
print(f"\nOrder Book for {symbol}:")
print("\nTop 5 Bids (Buy Orders):")
print(bids_df.head())
print("\nTop 5 Asks (Sell Orders):")
print(asks_df.head())
# Spread hesapla
best_bid = bids_df['price'].iloc[0]
best_ask = asks_df['price'].iloc[0]
spread = best_ask - best_bid
spread_percent = (spread / best_bid) * 100
print(f"\nBest Bid: ${best_bid:.2f}")
print(f"Best Ask: ${best_ask:.2f}")
print(f"Spread: ${spread:.2f} ({spread_percent:.3f}%)")
return {
'bids': bids_df,
'asks': asks_df,
'spread': spread,
'spread_percent': spread_percent
}
except BinanceAPIException as e:
print(f"Error: {e}")
return None
# Kullanım
order_book = get_order_book('BTCUSDT', limit=20)
|
Account Bilgileri ve Bakiye Yönetimi
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
| def get_account_info():
"""
Account bilgilerini al
"""
try:
account = client.get_account()
print("Account Information:")
print(f"Maker Commission: {account['makerCommission']}")
print(f"Taker Commission: {account['takerCommission']}")
print(f"Can Trade: {account['canTrade']}")
print(f"Can Withdraw: {account['canWithdraw']}")
# Balances'ları filtrele (0'dan büyük olanlar)
balances = [
balance for balance in account['balances']
if float(balance['free']) > 0 or float(balance['locked']) > 0
]
print(f"\nAssets with Balance: {len(balances)}")
return account
except BinanceAPIException as e:
print(f"Error: {e}")
return None
def get_asset_balance(asset='BTC'):
"""
Belirli bir asset'in bakiyesini al
Parameters:
asset (str): Asset sembolü (BTC, ETH, USDT, etc.)
Returns:
dict: Balance bilgisi
"""
try:
balance = client.get_asset_balance(asset=asset)
free = float(balance['free'])
locked = float(balance['locked'])
total = free + locked
print(f"\n{asset} Balance:")
print(f"Free: {free:.8f}")
print(f"Locked: {locked:.8f}")
print(f"Total: {total:.8f}")
return balance
except BinanceAPIException as e:
print(f"Error: {e}")
return None
def get_all_balances():
"""
Tüm asset'lerin bakiyesini al ve DataFrame'e dönüştür
"""
try:
account = client.get_account()
balances = account['balances']
# DataFrame'e dönüştür
df = pd.DataFrame(balances)
df['free'] = df['free'].astype(float)
df['locked'] = df['locked'].astype(float)
df['total'] = df['free'] + df['locked']
# Sadece bakiyesi olan asset'leri göster
df = df[df['total'] > 0].sort_values('total', ascending=False)
print("\nAll Balances:")
print(df)
return df
except BinanceAPIException as e:
print(f"Error: {e}")
return None
# Kullanım
get_account_info()
get_asset_balance('USDT')
all_balances = get_all_balances()
|
Order Placement (Emir Verme)
Şekil 2: Python trading bot mimarisi
Market Order
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
| from binance.enums import *
def place_market_order(symbol, side, quantity):
"""
Market order ver (anlık fiyattan al/sat)
Parameters:
symbol (str): Trading pair (örn: 'BTCUSDT')
side (str): 'BUY' veya 'SELL'
quantity (float): Miktar
Returns:
dict: Order bilgisi
"""
try:
# Market order oluştur
order = client.create_order(
symbol=symbol,
side=side,
type=ORDER_TYPE_MARKET,
quantity=quantity
)
print(f"\nMarket Order Placed:")
print(f"Symbol: {order['symbol']}")
print(f"Side: {order['side']}")
print(f"Quantity: {order['executedQty']}")
print(f"Status: {order['status']}")
print(f"Order ID: {order['orderId']}")
# Fill bilgilerini göster
if 'fills' in order:
total_cost = sum(float(fill['price']) * float(fill['qty'])
for fill in order['fills'])
avg_price = total_cost / float(order['executedQty'])
print(f"Average Fill Price: ${avg_price:.2f}")
print(f"Total Cost: ${total_cost:.2f}")
return order
except BinanceAPIException as e:
print(f"Order Error: {e}")
return None
except Exception as e:
print(f"Unexpected Error: {e}")
return None
|
Gerçek para ile order vermeden önce mutlaka Testnet üzerinde test edin! Yanlış bir order geri alınamaz.
Limit Order
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
| def place_limit_order(symbol, side, quantity, price):
"""
Limit order ver (belirli fiyattan al/sat)
Parameters:
symbol (str): Trading pair
side (str): 'BUY' veya 'SELL'
quantity (float): Miktar
price (float): Fiyat
Returns:
dict: Order bilgisi
"""
try:
order = client.create_order(
symbol=symbol,
side=side,
type=ORDER_TYPE_LIMIT,
timeInForce=TIME_IN_FORCE_GTC, # Good Till Cancel
quantity=quantity,
price=str(price)
)
print(f"\nLimit Order Placed:")
print(f"Symbol: {order['symbol']}")
print(f"Side: {order['side']}")
print(f"Quantity: {order['origQty']}")
print(f"Price: ${float(order['price']):,.2f}")
print(f"Status: {order['status']}")
print(f"Order ID: {order['orderId']}")
return order
except BinanceAPIException as e:
print(f"Order Error: {e}")
return None
# Örnek: BTC'yi 40000 USDT'den almak için limit order
# order = place_limit_order('BTCUSDT', SIDE_BUY, 0.001, 40000)
|
Stop-Loss Order
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
| def place_stop_loss_order(symbol, side, quantity, stop_price, limit_price=None):
"""
Stop-loss order ver (belirli fiyata gelince sat)
Parameters:
symbol (str): Trading pair
side (str): Genellikle 'SELL'
quantity (float): Miktar
stop_price (float): Trigger price
limit_price (float, optional): Limit price (None ise stop-market)
Returns:
dict: Order bilgisi
"""
try:
if limit_price is None:
# Stop-Loss Market Order
order = client.create_order(
symbol=symbol,
side=side,
type=ORDER_TYPE_STOP_LOSS,
quantity=quantity,
stopPrice=str(stop_price)
)
else:
# Stop-Loss Limit Order
order = client.create_order(
symbol=symbol,
side=side,
type=ORDER_TYPE_STOP_LOSS_LIMIT,
timeInForce=TIME_IN_FORCE_GTC,
quantity=quantity,
price=str(limit_price),
stopPrice=str(stop_price)
)
print(f"\nStop-Loss Order Placed:")
print(f"Symbol: {order['symbol']}")
print(f"Side: {order['side']}")
print(f"Type: {order['type']}")
print(f"Quantity: {order['origQty']}")
print(f"Stop Price: ${float(order['stopPrice']):,.2f}")
print(f"Order ID: {order['orderId']}")
return order
except BinanceAPIException as e:
print(f"Order Error: {e}")
return None
# Örnek: BTC'yi 38000'de sat (stop-loss)
# order = place_stop_loss_order('BTCUSDT', SIDE_SELL, 0.001, 38000)
|
OCO (One-Cancels-the-Other) Order
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
| def place_oco_order(symbol, side, quantity, price, stop_price, stop_limit_price):
"""
OCO order ver (take-profit + stop-loss birlikte)
Parameters:
symbol (str): Trading pair
side (str): 'SELL' (genellikle)
quantity (float): Miktar
price (float): Take-profit price
stop_price (float): Stop-loss trigger price
stop_limit_price (float): Stop-loss limit price
Returns:
dict: Order bilgisi
"""
try:
order = client.create_oco_order(
symbol=symbol,
side=side,
quantity=quantity,
price=str(price),
stopPrice=str(stop_price),
stopLimitPrice=str(stop_limit_price),
stopLimitTimeInForce=TIME_IN_FORCE_GTC
)
print(f"\nOCO Order Placed:")
print(f"Symbol: {symbol}")
print(f"Order List ID: {order['orderListId']}")
print(f"Take Profit Price: ${price:.2f}")
print(f"Stop Loss Price: ${stop_price:.2f}")
for report in order['orderReports']:
print(f"\n Order ID: {report['orderId']}")
print(f" Type: {report['type']}")
print(f" Status: {report['status']}")
return order
except BinanceAPIException as e:
print(f"Order Error: {e}")
return None
# Örnek: BTC aldıktan sonra 45000'de kâr al veya 38000'de zarar kes
# order = place_oco_order('BTCUSDT', SIDE_SELL, 0.001, 45000, 38000, 37900)
|
Order Yönetimi
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
| def get_open_orders(symbol=None):
"""
Açık emirleri listele
Parameters:
symbol (str, optional): Belirli bir symbol için (None ise hepsi)
Returns:
list: Açık order'lar
"""
try:
if symbol:
orders = client.get_open_orders(symbol=symbol)
else:
orders = client.get_open_orders()
print(f"\nOpen Orders: {len(orders)}")
for order in orders:
print(f"\nOrder ID: {order['orderId']}")
print(f"Symbol: {order['symbol']}")
print(f"Type: {order['type']}")
print(f"Side: {order['side']}")
print(f"Price: {order['price']}")
print(f"Quantity: {order['origQty']}")
print(f"Filled: {order['executedQty']}")
print(f"Status: {order['status']}")
return orders
except BinanceAPIException as e:
print(f"Error: {e}")
return []
def cancel_order(symbol, order_id):
"""
Belirli bir order'ı iptal et
Parameters:
symbol (str): Trading pair
order_id (int): Order ID
Returns:
dict: İptal bilgisi
"""
try:
result = client.cancel_order(
symbol=symbol,
orderId=order_id
)
print(f"\nOrder Cancelled:")
print(f"Symbol: {result['symbol']}")
print(f"Order ID: {result['orderId']}")
print(f"Status: {result['status']}")
return result
except BinanceAPIException as e:
print(f"Cancel Error: {e}")
return None
def cancel_all_orders(symbol):
"""
Bir symbol için tüm açık order'ları iptal et
Parameters:
symbol (str): Trading pair
Returns:
list: İptal edilen order'lar
"""
try:
result = client.cancel_open_orders(symbol=symbol)
print(f"\nAll orders cancelled for {symbol}")
print(f"Cancelled: {len(result)} orders")
return result
except BinanceAPIException as e:
print(f"Cancel Error: {e}")
return None
def get_order_history(symbol, limit=10):
"""
Geçmiş order'ları getir
Parameters:
symbol (str): Trading pair
limit (int): Maksimum order sayısı
Returns:
list: Order history
"""
try:
orders = client.get_all_orders(symbol=symbol, limit=limit)
print(f"\nOrder History for {symbol}: {len(orders)} orders")
df = pd.DataFrame(orders)
if not df.empty:
df['time'] = pd.to_datetime(df['time'], unit='ms')
df['price'] = df['price'].astype(float)
df['executedQty'] = df['executedQty'].astype(float)
print(df[['time', 'side', 'type', 'price', 'executedQty', 'status']].tail())
return orders
except BinanceAPIException as e:
print(f"Error: {e}")
return []
# Kullanım
open_orders = get_open_orders('BTCUSDT')
# cancel_order('BTCUSDT', order_id=12345678)
# cancel_all_orders('BTCUSDT')
history = get_order_history('BTCUSDT', limit=20)
|
WebSocket ile Gerçek Zamanlı Veri
WebSocket, gerçek zamanlı piyasa verilerini almak için en verimli yöntemdir.
WebSocket kullanarak REST API’ye sürekli request göndermekten kaçının. Bu hem rate limit’lere takılmanızı önler hem de daha düşük gecikme sağlar.
Fiyat Takibi
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
| from binance.streams import ThreadedWebsocketManager
import time
# WebSocket Manager oluştur
twm = ThreadedWebsocketManager(
api_key=os.getenv('BINANCE_API_KEY'),
api_secret=os.getenv('BINANCE_SECRET_KEY')
)
# Fiyat güncellemelerini handle et
def handle_price_update(msg):
"""
WebSocket price update callback
"""
if msg['e'] == 'error':
print(f"Error: {msg['m']}")
else:
symbol = msg['s']
price = float(msg['c']) # Close price
volume = float(msg['v']) # Volume
change = float(msg['P']) # Price change percent
print(f"{symbol}: ${price:,.2f} | Change: {change:+.2f}% | Volume: {volume:,.2f}")
# WebSocket başlat
twm.start()
# Ticker stream'i başlat
twm.start_symbol_ticker_socket(
callback=handle_price_update,
symbol='BTCUSDT'
)
print("WebSocket started. Press Ctrl+C to stop...")
try:
# Stream'i çalışır durumda tut
while True:
time.sleep(1)
except KeyboardInterrupt:
print("\nStopping WebSocket...")
twm.stop()
|
Kline (Candlestick) Stream
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
| def handle_kline_update(msg):
"""
Candlestick update callback
"""
if msg['e'] == 'error':
print(f"Error: {msg['m']}")
return
kline = msg['k']
print(f"\nKline Update for {kline['s']}:")
print(f"Interval: {kline['i']}")
print(f"Open: ${float(kline['o']):,.2f}")
print(f"High: ${float(kline['h']):,.2f}")
print(f"Low: ${float(kline['l']):,.2f}")
print(f"Close: ${float(kline['c']):,.2f}")
print(f"Volume: {float(kline['v']):,.2f}")
print(f"Is Closed: {kline['x']}")
# Kline stream başlat
twm.start()
twm.start_kline_socket(
callback=handle_kline_update,
symbol='BTCUSDT',
interval='1m'
)
print("Kline stream started...")
|
Order Book (Depth) Stream
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
| def handle_depth_update(msg):
"""
Order book update callback
"""
if msg['e'] == 'error':
print(f"Error: {msg['m']}")
return
bids = msg['b'] # Bid updates
asks = msg['a'] # Ask updates
print(f"\nOrder Book Update for {msg['s']}:")
if bids:
print("Bid Updates:")
for bid in bids[:5]: # Top 5
price, quantity = float(bid[0]), float(bid[1])
print(f" ${price:,.2f} x {quantity:.4f}")
if asks:
print("Ask Updates:")
for ask in asks[:5]: # Top 5
price, quantity = float(ask[0]), float(ask[1])
print(f" ${price:,.2f} x {quantity:.4f}")
# Depth stream başlat
twm.start()
twm.start_depth_socket(
callback=handle_depth_update,
symbol='BTCUSDT'
)
print("Depth stream started...")
|
Trade Stream
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| def handle_trade_update(msg):
"""
Individual trade update callback
"""
if msg['e'] == 'error':
print(f"Error: {msg['m']}")
return
print(f"\nNew Trade for {msg['s']}:")
print(f"Price: ${float(msg['p']):,.2f}")
print(f"Quantity: {float(msg['q']):.4f}")
print(f"Buyer is Maker: {msg['m']}")
print(f"Trade Time: {pd.to_datetime(msg['T'], unit='ms')}")
# Trade stream başlat
twm.start()
twm.start_trade_socket(
callback=handle_trade_update,
symbol='BTCUSDT'
)
print("Trade stream started...")
|
User Data Stream
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
| def handle_user_update(msg):
"""
User data stream callback (orders, balances)
"""
event_type = msg['e']
if event_type == 'executionReport':
# Order update
print(f"\nOrder Update:")
print(f"Symbol: {msg['s']}")
print(f"Side: {msg['S']}")
print(f"Type: {msg['o']}")
print(f"Status: {msg['X']}")
print(f"Price: {msg['p']}")
print(f"Quantity: {msg['q']}")
print(f"Filled: {msg['z']}")
elif event_type == 'outboundAccountPosition':
# Balance update
print(f"\nBalance Update:")
for balance in msg['B']:
if float(balance['f']) > 0 or float(balance['l']) > 0:
print(f"{balance['a']}: Free={balance['f']}, Locked={balance['l']}")
# User data stream başlat
twm.start()
twm.start_user_socket(callback=handle_user_update)
print("User data stream started...")
|
Trading Bot Örneği
Basit bir trading bot implementasyonu:
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
| import time
from loguru import logger
class SimpleTradingBot:
"""
Basit bir trading bot - SMA crossover stratejisi
"""
def __init__(self, symbol='BTCUSDT', interval='5m', short_period=10, long_period=30):
self.symbol = symbol
self.interval = interval
self.short_period = short_period
self.long_period = long_period
self.position = None # None, 'LONG', 'SHORT'
self.entry_price = 0
logger.add("trading_bot.log", rotation="1 day")
logger.info(f"Bot initialized for {symbol}")
def get_sma(self, period):
"""
SMA (Simple Moving Average) hesapla
"""
klines = client.get_klines(
symbol=self.symbol,
interval=self.interval,
limit=period
)
closes = [float(k[4]) for k in klines]
sma = sum(closes) / len(closes)
return sma
def check_signal(self):
"""
Trading sinyali kontrol et
"""
short_sma = self.get_sma(self.short_period)
long_sma = self.get_sma(self.long_period)
current_price = float(client.get_symbol_ticker(symbol=self.symbol)['price'])
logger.info(f"Price: ${current_price:.2f} | Short SMA: ${short_sma:.2f} | Long SMA: ${long_sma:.2f}")
# Bullish crossover (AL)
if short_sma > long_sma and self.position is None:
return 'BUY', current_price
# Bearish crossover (SAT)
elif short_sma < long_sma and self.position == 'LONG':
return 'SELL', current_price
return None, current_price
def execute_trade(self, signal, price):
"""
Trading işlemini gerçekleştir
"""
try:
if signal == 'BUY':
# UYARI: Bu örnek kodda miktar sabit, gerçek kullanımda hesaplayın
quantity = 0.001
logger.info(f"BUY signal at ${price:.2f}")
# order = place_market_order(self.symbol, SIDE_BUY, quantity)
self.position = 'LONG'
self.entry_price = price
logger.info(f"Position opened: LONG at ${price:.2f}")
elif signal == 'SELL' and self.position == 'LONG':
quantity = 0.001
profit = (price - self.entry_price) / self.entry_price * 100
logger.info(f"SELL signal at ${price:.2f} | Profit: {profit:.2f}%")
# order = place_market_order(self.symbol, SIDE_SELL, quantity)
self.position = None
self.entry_price = 0
logger.info(f"Position closed at ${price:.2f}")
except Exception as e:
logger.error(f"Trade execution error: {e}")
def run(self, check_interval=60):
"""
Bot'u çalıştır
Parameters:
check_interval (int): Kontrol aralığı (saniye)
"""
logger.info(f"Bot started. Checking every {check_interval} seconds...")
try:
while True:
signal, price = self.check_signal()
if signal:
self.execute_trade(signal, price)
time.sleep(check_interval)
except KeyboardInterrupt:
logger.info("Bot stopped by user")
except Exception as e:
logger.error(f"Bot error: {e}")
|
Herhangi bir trading botunu production’a almadan önce en az 1 ay backtest ve paper trading yapın. Risk yönetimi kurallarını mutlaka uygulayın.
Risk Yönetimi
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
| class RiskManager:
"""
Risk yönetimi için yardımcı sınıf
"""
def __init__(self, max_position_size_usd=1000, max_loss_percent=2):
self.max_position_size_usd = max_position_size_usd
self.max_loss_percent = max_loss_percent
def calculate_position_size(self, entry_price, stop_loss_price, account_balance):
"""
Position size hesapla (risk bazlı)
Parameters:
entry_price (float): Giriş fiyatı
stop_loss_price (float): Stop loss fiyatı
account_balance (float): Hesap bakiyesi (USDT)
Returns:
float: Position size
"""
# Risk miktarı (USDT)
risk_amount = account_balance * (self.max_loss_percent / 100)
# Fiyat farkı (risk per unit)
price_difference = abs(entry_price - stop_loss_price)
# Position size
position_size = risk_amount / price_difference
# Maximum position size kontrolü
max_quantity = self.max_position_size_usd / entry_price
position_size = min(position_size, max_quantity)
return position_size
def check_daily_loss_limit(self, trades_today):
"""
Günlük zarar limitini kontrol et
Parameters:
trades_today (list): Bugünkü işlemler
Returns:
bool: Trading devam edilebilir mi?
"""
total_pnl = sum(trade['pnl'] for trade in trades_today)
# Günlük maksimum zarar: %5
max_daily_loss = 0.05
if total_pnl < -max_daily_loss:
logger.warning(f"Daily loss limit reached: {total_pnl:.2%}")
return False
return True
def calculate_stop_loss(self, entry_price, side, atr, multiplier=2):
"""
ATR bazlı stop loss hesapla
Parameters:
entry_price (float): Giriş fiyatı
side (str): 'BUY' veya 'SELL'
atr (float): Average True Range
multiplier (float): ATR çarpanı
Returns:
float: Stop loss fiyatı
"""
stop_distance = atr * multiplier
if side == SIDE_BUY:
stop_loss = entry_price - stop_distance
else:
stop_loss = entry_price + stop_distance
return stop_loss
def calculate_take_profit(self, entry_price, stop_loss, risk_reward_ratio=2):
"""
Risk/reward ratio bazlı take profit hesapla
Parameters:
entry_price (float): Giriş fiyatı
stop_loss (float): Stop loss fiyatı
risk_reward_ratio (float): Risk/reward oranı
Returns:
float: Take profit fiyatı
"""
risk = abs(entry_price - stop_loss)
reward = risk * risk_reward_ratio
if entry_price > stop_loss: # Long position
take_profit = entry_price + reward
else: # Short position
take_profit = entry_price - reward
return take_profit
# Kullanım
risk_manager = RiskManager(max_position_size_usd=1000, max_loss_percent=2)
# Example: BTC long position
entry = 40000
stop_loss = 39000
account_balance = 10000 # USDT
position_size = risk_manager.calculate_position_size(entry, stop_loss, account_balance)
print(f"Position Size: {position_size:.4f} BTC")
take_profit = risk_manager.calculate_take_profit(entry, stop_loss, risk_reward_ratio=2.5)
print(f"Take Profit: ${take_profit:.2f}")
|
Error Handling ve Best Practices
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
| from binance.exceptions import (
BinanceAPIException,
BinanceOrderException,
BinanceRequestException
)
import requests
from tenacity import retry, stop_after_attempt, wait_exponential
class BinanceTrader:
"""
Gelişmiş error handling ile Binance trader
"""
def __init__(self, api_key, secret_key):
self.client = Client(api_key, secret_key)
@retry(
stop=stop_after_attempt(3),
wait=wait_exponential(multiplier=1, min=4, max=10)
)
def safe_api_call(self, func, *args, **kwargs):
"""
Retry logic ile güvenli API çağrısı
"""
try:
return func(*args, **kwargs)
except BinanceAPIException as e:
logger.error(f"Binance API Error: {e.status_code} - {e.message}")
# Rate limit hatası
if e.status_code == 429:
logger.warning("Rate limit exceeded, waiting...")
time.sleep(60)
raise # Retry için
# Invalid order
elif e.status_code == 400:
logger.error("Invalid order parameters")
return None
# Insufficient balance
elif 'insufficient' in str(e).lower():
logger.error("Insufficient balance for order")
return None
else:
raise
except BinanceRequestException as e:
logger.error(f"Request Error: {e}")
raise # Retry için
except requests.exceptions.RequestException as e:
logger.error(f"Network Error: {e}")
raise # Retry için
except Exception as e:
logger.error(f"Unexpected Error: {e}")
return None
def validate_order_params(self, symbol, quantity, price=None):
"""
Order parametrelerini valide et
"""
try:
# Symbol bilgisini al
info = self.client.get_symbol_info(symbol)
if not info:
logger.error(f"Invalid symbol: {symbol}")
return False
# Filters kontrolü
for f in info['filters']:
# LOT_SIZE kontrolü
if f['filterType'] == 'LOT_SIZE':
min_qty = float(f['minQty'])
max_qty = float(f['maxQty'])
step_size = float(f['stepSize'])
if quantity < min_qty:
logger.error(f"Quantity {quantity} below minimum {min_qty}")
return False
if quantity > max_qty:
logger.error(f"Quantity {quantity} above maximum {max_qty}")
return False
# PRICE_FILTER kontrolü
if f['filterType'] == 'PRICE_FILTER' and price:
min_price = float(f['minPrice'])
max_price = float(f['maxPrice'])
tick_size = float(f['tickSize'])
if price < min_price or price > max_price:
logger.error(f"Price {price} out of range")
return False
return True
except Exception as e:
logger.error(f"Validation error: {e}")
return False
def place_order_safe(self, symbol, side, quantity, order_type='MARKET', price=None):
"""
Güvenli order placement
"""
# Parametreleri valide et
if not self.validate_order_params(symbol, quantity, price):
return None
# Order'ı oluştur
order_params = {
'symbol': symbol,
'side': side,
'type': order_type,
'quantity': quantity
}
if order_type == ORDER_TYPE_LIMIT and price:
order_params['timeInForce'] = TIME_IN_FORCE_GTC
order_params['price'] = str(price)
# API çağrısı yap
order = self.safe_api_call(
self.client.create_order,
**order_params
)
if order:
logger.info(f"Order placed successfully: {order['orderId']}")
return order
# Kullanım
trader = BinanceTrader(
api_key=os.getenv('BINANCE_API_KEY'),
secret_key=os.getenv('BINANCE_SECRET_KEY')
)
# order = trader.place_order_safe('BTCUSDT', SIDE_BUY, 0.001)
|
Monitoring ve Logging
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
| from loguru import logger
import sys
# Logging konfigürasyonu
logger.remove() # Default handler'ı kaldır
# Console logger
logger.add(
sys.stdout,
format="<green>{time:YYYY-MM-DD HH:mm:ss}</green> | <level>{level: <8}</level> | <cyan>{name}</cyan>:<cyan>{function}</cyan> - <level>{message}</level>",
level="INFO"
)
# File logger
logger.add(
"logs/trading_{time:YYYY-MM-DD}.log",
rotation="00:00", # Her gün yeni dosya
retention="30 days", # 30 gün sakla
compression="zip", # Eski logları sıkıştır
format="{time:YYYY-MM-DD HH:mm:ss} | {level: <8} | {name}:{function} - {message}",
level="DEBUG"
)
# Error logger
logger.add(
"logs/errors_{time:YYYY-MM-DD}.log",
rotation="00:00",
retention="90 days",
compression="zip",
format="{time:YYYY-MM-DD HH:mm:ss} | {level: <8} | {name}:{function} - {message}",
level="ERROR"
)
# Performance monitoring
class PerformanceMonitor:
"""
Trading performansını takip et
"""
def __init__(self):
self.trades = []
self.daily_pnl = {}
def log_trade(self, trade_data):
"""
İşlemi kaydet
"""
self.trades.append(trade_data)
date = trade_data['timestamp'].date()
if date not in self.daily_pnl:
self.daily_pnl[date] = []
self.daily_pnl[date].append(trade_data['pnl'])
logger.info(f"Trade logged: {trade_data['symbol']} | PnL: {trade_data['pnl']:.2f}")
def get_statistics(self):
"""
İstatistikleri hesapla
"""
if not self.trades:
return None
df = pd.DataFrame(self.trades)
stats = {
'total_trades': len(df),
'winning_trades': len(df[df['pnl'] > 0]),
'losing_trades': len(df[df['pnl'] < 0]),
'win_rate': (len(df[df['pnl'] > 0]) / len(df)) * 100,
'total_pnl': df['pnl'].sum(),
'avg_win': df[df['pnl'] > 0]['pnl'].mean() if len(df[df['pnl'] > 0]) > 0 else 0,
'avg_loss': df[df['pnl'] < 0]['pnl'].mean() if len(df[df['pnl'] < 0]) > 0 else 0,
'largest_win': df['pnl'].max(),
'largest_loss': df['pnl'].min(),
'profit_factor': abs(df[df['pnl'] > 0]['pnl'].sum() / df[df['pnl'] < 0]['pnl'].sum()) if len(df[df['pnl'] < 0]) > 0 else 0
}
return stats
def print_report(self):
"""
Rapor yazdır
"""
stats = self.get_statistics()
if not stats:
logger.info("No trades to report")
return
logger.info("\n" + "="*50)
logger.info("TRADING PERFORMANCE REPORT")
logger.info("="*50)
logger.info(f"Total Trades: {stats['total_trades']}")
logger.info(f"Winning Trades: {stats['winning_trades']}")
logger.info(f"Losing Trades: {stats['losing_trades']}")
logger.info(f"Win Rate: {stats['win_rate']:.2f}%")
logger.info(f"Total PnL: ${stats['total_pnl']:.2f}")
logger.info(f"Average Win: ${stats['avg_win']:.2f}")
logger.info(f"Average Loss: ${stats['avg_loss']:.2f}")
logger.info(f"Largest Win: ${stats['largest_win']:.2f}")
logger.info(f"Largest Loss: ${stats['largest_loss']:.2f}")
logger.info(f"Profit Factor: {stats['profit_factor']:.2f}")
logger.info("="*50 + "\n")
# Kullanım
monitor = PerformanceMonitor()
# İşlem kaydı
# trade = {
# 'timestamp': pd.Timestamp.now(),
# 'symbol': 'BTCUSDT',
# 'side': 'BUY',
# 'entry_price': 40000,
# 'exit_price': 41000,
# 'quantity': 0.1,
# 'pnl': 100
# }
# monitor.log_trade(trade)
# monitor.print_report()
|
Sonuç
Bu rehberde öğrendiğiniz teknikler sadece Binance için değil, CCXT kütüphanesi ile 100+ farklı exchange için de kullanılabilir.
Python ile Binance API entegrasyonu, kripto trading dünyasında güçlü otomasyonlar kurmanızı sağlar. Bu rehberde öğrendikleriniz:
- REST API: Market data çekme, order placement ve account yönetimi
- WebSocket: Gerçek zamanlı veri akışları ve event handling
- Trading Stratejileri: Basit SMA crossover bot implementasyonu
- Risk Yönetimi: Position sizing, stop loss ve take profit hesaplamaları
- Error Handling: Güvenli API çağrıları ve retry logic
- Monitoring: Performance tracking ve logging best practices
Önemli Hatırlatmalar:
- API key’lerinizi asla paylaşmayın ve git’e eklemeyin
- Test işlemlerinde Testnet kullanın
- Risk yönetimi kurallarına uyun
- Rate limit’lere dikkat edin
- Production’da comprehensive logging kullanın
- Her zaman stop loss kullanın
Trading bot geliştirmek teknik bilgi gerektirir ancak risk yönetimi daha da önemlidir. Küçük başlayın, test edin ve yavaş yavaş ölçeklendirin.
Kaynaklar
Resmi Dokümantasyon
Kütüphaneler
Öğrenme Kaynakları
Topluluklar
Başarılı ve güvenli trading’ler! 🚀📈