Skip to content

Commit d7f6956

Browse files
authoredDec 16, 2023
Add files via upload
1 parent 9050c93 commit d7f6956

18 files changed

+1947
-0
lines changed
 

‎.gitignore

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
.DS_Store
2+
*.ipynb
3+
*futures*
4+
*jaimin*
5+
*.csv
6+
*scrape*
7+
venv
8+
*limit*

‎binance_api.py

+317
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,317 @@
1+
import ccxt,getpip
2+
import time
3+
from datetime import datetime
4+
import json
5+
import os
6+
import sys
7+
8+
# Executes buying and selling
9+
class binance_api:
10+
11+
# Initialize
12+
def __init__(self, api_keys, logfile=False, block=False, account_json=None):
13+
self.api_keys = {'api_key':api_keys['binance_keys']['api_key'],'secret_key':api_keys['binance_keys']['secret_key']}
14+
self.exchange = ccxt.binance({'apiKey':self.api_keys['api_key'], 'secret':self.api_keys['secret_key']})
15+
self.logfile = logfile
16+
self.block = block
17+
self.started_time = datetime.now()
18+
self.account_json = account_json
19+
20+
# Set of tickers to block if specified
21+
if self.block:
22+
self.block_set = set()
23+
24+
# Reset the exchange
25+
def refresh_exchange(self):
26+
self.exchange = ccxt.binance({'apiKey':self.api_keys['api_key'], 'secret':self.api_keys['secret_key']})
27+
28+
# Buying of real cryto
29+
def buy_crypto(self, ticker, buy_volume):
30+
31+
# Try creating the buy order
32+
for i in range(10):
33+
try:
34+
buy_trade = self.exchange.create_order(ticker,'market','buy',buy_volume)
35+
break
36+
except Exception as e:
37+
print(e)
38+
if i == 9:
39+
print('Could not buy, exiting thread')
40+
exit()
41+
print('\nBuy did not work, trying again')
42+
43+
# Print buy
44+
try:
45+
if buy_trade.get('status') != 'open':
46+
avg_price = sum([float(x['price']) * float(x['qty']) for x in buy_trade['info']['fills']])/sum([float(x['qty']) for x in buy_trade['info']['fills']])
47+
print('\nBought %s of %s at %s with %s %s of fees on %s\n' % (buy_trade['amount']\
48+
, buy_trade['symbol'], avg_price, buy_trade['fee']['cost'], buy_trade['fee']['currency']\
49+
, datetime.now().strftime('%b %d - %H:%M:%S')))
50+
else:
51+
print('\nBought %.8f at %s\n' % (buy_volume, datetime.now().strftime('%b %d - %H:%M:%S')))
52+
except Exception as e:
53+
print(e)
54+
print('\nError in print of buy')
55+
56+
return buy_trade, buy_volume
57+
58+
# Selling of real crypto
59+
def sell_crypto(self, ticker, buy_volume, buy_trade):
60+
61+
# Try to sell 10 times
62+
for i in range(10):
63+
try:
64+
# Fees in USDT, Buy/Sell crypto amount is equal -- check if behaviour is the same when you have BNB in the wallet
65+
if ticker[-4:] == 'USDT':
66+
sell_volume = buy_volume
67+
# If fees in the returned trade (filled on order)
68+
elif buy_trade['fee']:
69+
if buy_trade['fee']['currency'] == 'BNB':
70+
sell_volume = buy_volume
71+
else:
72+
# Converting fee currency to buy currency
73+
ticker_pair = ticker.split('/')
74+
if ticker_pair[0] != buy_trade['fee']['currency']:
75+
fee_pair = [ticker_pair[0], buy_trade['fee']['currency']]
76+
fee_ticker = '/'.join(fee_pair)
77+
if fee_ticker not in tickers:
78+
fee_ticker = '/'.join(fee_pair[::-1])
79+
fee = self.exchange.fetchTicker(fee_ticker)
80+
fee_price = (fee['bid'] + fee['ask']) /2
81+
sell_volume = buy_volume - fee_price * buy_trade['fee']['cost']
82+
83+
# When fee currency is the same as the buy currency
84+
else:
85+
sell_volume = buy_volume - buy_trade['fee']['cost']
86+
else:
87+
sell_volume = buy_volume
88+
89+
sell_trade = self.exchange.create_order(ticker,'market','sell',sell_volume)
90+
break
91+
92+
except Exception as e:
93+
error = e
94+
if 'MIN_NOTIONAL' in str(error):
95+
buy_volume = buy_volume *1.0005
96+
elif 'insufficient balance' in str(error):
97+
buy_volume = buy_volume * 0.9995
98+
else:
99+
self.refresh_exchange()
100+
print(e)
101+
print('\n\nTrying to sell %.10f again' % buy_volume)
102+
103+
# Print sell
104+
if sell_trade['status'] != 'open':
105+
avg_price = sum([float(x['price']) * float(x['qty']) for x in sell_trade['info']['fills']])/sum([float(x['qty']) for x in sell_trade['info']['fills']])
106+
print('\nSold %s of %s at %s with %s %s of fees on %s' % (sell_trade['amount'], sell_trade['symbol'], avg_price\
107+
, sell_trade['fee']['cost'], sell_trade['fee']['currency'], datetime.now().strftime('%b %d - %H:%M:%S')))
108+
else:
109+
print('\nSold %.8f at %s' % (sell_volume, datetime.now().strftime('%b %d - %H:%M:%S')))
110+
111+
return sell_trade
112+
113+
114+
# Get data from self.exchange and print it
115+
def simulate_trade(self, buy, volume, ticker, conversion):
116+
if conversion[-4:] == 'USDT' and ticker[-4:] == 'USDT':
117+
usdpair = {'bid':1,'ask':1}
118+
else:
119+
usdpair = self.exchange.fetchTicker(conversion)
120+
if buy:
121+
bid_ask, buy_sell = 'ask', 'Buying'
122+
else:
123+
bid_ask, buy_sell = 'bid', 'Selling'
124+
try:
125+
trade_price = self.exchange.fetchTicker(ticker)[bid_ask]
126+
price = (usdpair['bid']+usdpair['ask'])/2
127+
print('\n{} {} at {:.8f} {} = ${:.6f}'.format(buy_sell, volume, trade_price, ticker, trade_price * volume * price))
128+
129+
except Exception as e:
130+
print (e, '\nError in fetching ticker info')
131+
trade = {'symbol': ticker,'side':'buy' if buy else 'sell', 'amount':volume, 'cost':trade_price * volume}
132+
133+
return trade
134+
135+
136+
# Summarise trade buy and sell
137+
def print_summary(self, simulate, ticker, buy_trade, sell_trades, conversion):
138+
139+
if not simulate:
140+
buy_id, sell_ids = buy_trade['info']['orderId'], [i['info']['orderId'] for i in sell_trades]
141+
buy_prices, sell_prices = [], []
142+
for i in range(20):
143+
try:
144+
trades = self.exchange.fetchMyTrades(ticker)
145+
break
146+
except Exception as e:
147+
print(e)
148+
print("Couldn't fetch trades, tying again")
149+
150+
# Loop over trades as one order could have had multiple fills
151+
for trade in trades[::-1]:
152+
if buy_id == trade['info']['orderId']:
153+
buy_prices.append({'amount':trade['amount'],'cost':trade['cost'],'fee':trade['fee']})
154+
elif trade['info']['orderId'] in sell_ids:
155+
sell_prices.append({'amount':trade['amount'],'cost':trade['cost'],'fee':trade['fee']}) # Actual return uses fills
156+
157+
buy_fee = sum([x['fee']['cost'] for x in buy_prices])
158+
sell_fee = sum([x['fee']['cost'] for x in sell_prices])
159+
160+
# Log fees
161+
for i in range(20):
162+
try:
163+
if buy_prices[0]['fee']['currency'] == 'BNB':
164+
bnb_dollar = self.exchange.fetch_ticker('BNB/USDT')
165+
bnb_price = (bnb_dollar['bid'] + bnb_dollar['ask']) / 2
166+
buy_fee_dollar = buy_fee * bnb_price
167+
if sell_prices[0]['fee']['currency'] == 'BNB':
168+
sell_fee_dollar = sell_fee * bnb_price
169+
elif buy_prices[0]['fee']['currency'] == 'USDT':
170+
buy_fee_dollar = buy_fee
171+
sell_fee_dollar = sell_fee
172+
else:
173+
buy_crypto_dollar = self.exchange.fetch_ticker(buy_prices[0]['fee']['currency']+'/USDT')
174+
sell_crypto_dollar = self.exchange.fetch_ticker(sell_prices[0]['fee']['currency']+'/USDT')
175+
buy_fee_price = (buy_crypto_dollar['bid']+buy_crypto_dollar['ask'])/2
176+
sell_fee_price = (sell_crypto_dollar['bid']+sell_crypto_dollar['ask'])/2
177+
buy_fee_dollar = buy_fee_price * buy_fee
178+
sell_fee_dollar = sell_fee_price * sell_fee
179+
180+
ticker_pair = ticker.split('/')
181+
if ticker_pair[1] == 'USDT':
182+
ticker_info = {'bid':1,'ask':1}
183+
else:
184+
ticker_info = self.exchange.fetch_ticker(ticker_pair[1]+'/'+'USDT')
185+
break
186+
except Exception as e:
187+
print(e)
188+
print('\nError in printing executed trades')
189+
else:
190+
sell_prices, buy_prices = sell_trades, [buy_trade]
191+
sell_fee_dollar, buy_fee_dollar = 0, 0
192+
if ticker[-4:] == 'USDT':
193+
ticker_info = {'bid':1, 'ask':1}
194+
else:
195+
ticker_info = self.exchange.fetch_ticker(ticker.split('/')[1]+'/'+'USDT')
196+
197+
buy_total = sum(i['cost'] for i in buy_prices)
198+
sell_total = sum([i['cost'] for i in sell_prices])
199+
avg_bid_ask = (ticker_info['bid'] + ticker_info['ask']) / 2
200+
201+
gain_loss = (sell_total - buy_total) * avg_bid_ask - sell_fee_dollar - buy_fee_dollar
202+
gain_loss_percent = gain_loss / (buy_total * avg_bid_ask - sell_fee_dollar - buy_fee_dollar) * 100
203+
204+
gain_text = '\nProfit/Loss: $%.6f %.3f%%' % (gain_loss, gain_loss_percent)
205+
print(gain_text)
206+
207+
return gain_text, buy_total, sell_total
208+
209+
# Send a telegram of the profits and losses
210+
def send_telegram(self, ticker, buy_total, sell_total, gain_text, status, simulate):
211+
212+
# Sending a telegram message to myself
213+
import telegram
214+
with open('../telegram_keys.json') as json_file:
215+
telegram_dict = json.load(json_file)
216+
if type(status) == dict:
217+
full_info_text = '(%s) %s\nBought %.6f and sold %.6f BTC\n\n@%s - %s:\n"%s"\n' % (ticker, gain_text, float(buy_total), \
218+
float(sell_total), status['url'], status['update_time'].strftime('%m/%d %H:%M:%S'), status['update_text'])
219+
else:
220+
try:
221+
full_text = status.text
222+
except:
223+
full_text = status.full_text
224+
full_info_text = '(%s) %s\nBought %.6f and sold %.6f BTC\n\n@%s - %s:\n"%s"\n' % (ticker, gain_text, float(buy_total), \
225+
float(sell_total), status.user.screen_name, status.created_at.strftime('%m/%d %H:%M:%S'), full_text)
226+
227+
bot = telegram.Bot(token=telegram_dict['api_key'])
228+
bot.send_message(chat_id=telegram_dict['chat_id'], text=full_info_text)
229+
230+
231+
# Log the trade
232+
def log_trade(self, ticker, buy_volume, hold_times, buy_trade, sell_trades, gain_text, status, simulate):
233+
# Log trade
234+
now = datetime.now().strftime("%y-%m-%d_%H:%M:%S")
235+
236+
# Saving name format: time_started, json_file_used, simluation/live
237+
with open("prev_trades/trades_%s_binance_%s_%s.txt" % (self.started_time.strftime('%Y-%m-%d_%H-%M-%S'), self.account_json, 'simulation' if simulate else 'live'), "a") as log_name:
238+
# If status is a dict, the message was from a web scrape
239+
if type(status) == dict:
240+
json.dump({'url':status['url'],'update_text':status['update_text'],'update_time':status['update_time'].strftime('%Y-%m-%d_%H:%M:%S'),'ticker':ticker,'hold_times':hold_times,'complete_time':now,'buy_volume':buy_volume,'buy':buy_trade,'sell':sell_trades,'telegram':gain_text}, log_name)
241+
242+
# If tweet from stream or query
243+
else:
244+
try:
245+
full_text = status.text
246+
except:
247+
full_text = status.full_text
248+
json.dump({'user':status.user.screen_name,'tweet':full_text,'tweet_time':status.created_at.strftime('%Y-%m-%d_%H:%M:%S'),'ticker':ticker,'hold_times':hold_times,'complete_time':now,'buy_volume':buy_volume,'buy':buy_trade,'sell':sell_trades,'telegram':gain_text}, log_name)
249+
log_name.write('\n')
250+
251+
252+
# Execute trade
253+
def execute_trade(self, pair, hold_times=60, buy_volume=50, simulate=False, status=None):
254+
255+
# Dealing with buy_sell volume pair or just a buy_volume
256+
if type(buy_volume) != list:
257+
sell_volumes = [buy_volume / len(hold_times) for _ in hold_times]
258+
else:
259+
sell_volumes = buy_volume[1]
260+
buy_volume = buy_volume[0]
261+
262+
# Ticker and convesion
263+
ticker = pair[0]+'/'+pair[1]
264+
tousd1 = pair[0]+'/USDT'
265+
tousd2 = pair[1]+'/USDT'
266+
267+
# If there is a block put on trading this ticker
268+
if self.block:
269+
if ticker in self.block_set:
270+
print('\nTrade of ' + ticker + ' blocked in ' + str(self.block_set))
271+
return
272+
# When bought add and blocker flag set
273+
self.block_set.add(ticker)
274+
print('Added to blockset '+str(self.block_set))
275+
276+
# Buy order
277+
if not simulate:
278+
buy_trade, buy_volume = self.buy_crypto(ticker, buy_volume)
279+
else:
280+
buy_trade = self.simulate_trade(True, buy_volume, ticker, tousd2)
281+
282+
283+
# Sell in multiple stages based on hold_times
284+
prev_sell_time = 0
285+
sell_trades = []
286+
for hold, sell_volume in zip(hold_times, sell_volumes):
287+
time.sleep(hold - prev_sell_time)
288+
prev_sell_time = hold
289+
290+
# Sell order
291+
if not simulate:
292+
sell_trades.append(self.sell_crypto(ticker, sell_volume, buy_trade))
293+
else:
294+
sell_trades.append(self.simulate_trade(False, sell_volume, ticker, tousd2))
295+
296+
# Remove block when trade finishes
297+
if self.block:
298+
self.block_set.remove(ticker)
299+
print('Removing %s from block set' % (ticker))
300+
301+
print('\n\nTRADE FINISHED\n')
302+
303+
# Print summary and log
304+
try:
305+
gain_text, buy_total, sell_total = self.print_summary(simulate, ticker, buy_trade, sell_trades, tousd2)
306+
except Exception as e:
307+
print('\nFailed to print summary\n')
308+
print(e)
309+
310+
# Send telegram message
311+
if 'telegram_keys.json' in os.listdir('../') and not simulate:
312+
self.send_telegram(ticker, buy_total, sell_total, gain_text, status, simulate)
313+
314+
# Log trade
315+
if self.logfile:
316+
self.log_trade(ticker, buy_volume, hold_times, buy_trade, sell_trades, gain_text, status, simulate)
317+

0 commit comments

Comments
 (0)
Please sign in to comment.