-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathTradingBot.py
309 lines (263 loc) · 13.2 KB
/
TradingBot.py
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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
from time import sleep
from pyfiglet import Figlet
import requests, datetime, BinanceAPI
from TelegramBots import TelegramBot
import json
from pytz import timezone
# Constante con el Token de la API para obtener el valor de los indicadores.
TOKEN_API_INDICATORS = ""
testnet = "https://testnet.binancefuture.com"
# Claves Daniel para testear
KEY = ""
SECRET = ""
BinanceAPI = BinanceAPI.BinanceAPI(KEY, SECRET)
madrid = timezone('Europe/Madrid')
def getDMI(objetivo):
# Peticion GET al endpoint de la API que devuelve los valores de los indicadores. Seria muy interesante obtener
# el ADX y el resto de valores de Binance Futuros USDM.
# https://api.taapi.io/dmi?secret=
# .eyJlbWFpbCI6InJvYWR0bzFtaWxsaW9uMjAyNkBnbWFpbC5jb20iLCJpYXQiOjE2NDMxMTE4NTgsImV4cCI6Nzk1MDMxMTg1OH0
# .GmJoKq_wyWfAhkfBA0jJp7kCELHCZVfycDYvexbRytM&exchange=binanceusdm&symbol=BTC/USDT&interval=15m
r = requests.get(
'https://api.taapi.io/dmi?secret=' + TOKEN_API_INDICATORS + '&exchange=binance&symbol=BTC/USDT&interval=15m'
'&backtracks=2')
values = r.json()
# Compruebo si existe algun problema al realizar la peticion.
if r.status_code != 200:
return False, -1
else:
# Convierto la variable que posee los valores en JSON para que puedan ser utilizados con python de manera sencilla
values = json.dumps(values)
values = json.loads(values)
lista_dmis = []
for v in values:
if objetivo == -1:
return [False, -1]
elif objetivo == 0:
lista_dmis.append(float(v["minusdi"]))
elif objetivo == 1:
lista_dmis.append(float(v["plusdi"]))
return True, lista_dmis
def getMA50():
# Peticion GET al endpoint de la API que devuelve los valores de los indicadores. Seria muy interesante obtener
# el ADX y el resto de valores de Binance Futuros USDM.
# https://api.taapi.io/dmi?secret=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
# .eyJlbWFpbCI6InJvYWR0bzFtaWxsaW9uMjAyNkBnbWFpbC5jb20iLCJpYXQiOjE2NDMxMTE4NTgsImV4cCI6Nzk1MDMxMTg1OH0
# .GmJoKq_wyWfAhkfBA0jJp7kCELHCZVfycDYvexbRytM&exchange=binanceusdm&symbol=BTC/USDT&interval=15m
r = requests.get(
'https://api.taapi.io/ma?secret=' + TOKEN_API_INDICATORS + '&exchange=binance&symbol=BTC/USDT&interval=15m'
'&optInTimePeriod=50')
values = r.json()
# Compruebo si existe algun problema al realizar la peticion.
if r.status_code != 200:
return [False, -1]
else:
# Convierto la variable que posee los valores en JSON para que puedan ser utilizados con python de manera sencilla
values = json.dumps(values)
values = json.loads(values)
return [True, values]
def getMA200():
# Peticion GET al endpoint de la API que devuelve los valores de los indicadores. Seria muy interesante obtener
# el ADX y el resto de valores de Binance Futuros USDM.
# https://api.taapi.io/dmi?secret=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
# .eyJlbWFpbCI6InJvYWR0bzFtaWxsaW9uMjAyNkBnbWFpbC5jb20iLCJpYXQiOjE2NDMxMTE4NTgsImV4cCI6Nzk1MDMxMTg1OH0
# .GmJoKq_wyWfAhkfBA0jJp7kCELHCZVfycDYvexbRytM&exchange=binanceusdm&symbol=BTC/USDT&interval=15m
r = requests.get(
'https://api.taapi.io/ma?secret=' + TOKEN_API_INDICATORS + '&exchange=binance&symbol=BTC/USDT&interval=15m'
'&optInTimePeriod=200')
values = r.json()
# Compruebo si existe algun problema al realizar la peticion.
if r.status_code != 200:
return [False, -1]
else:
# Convierto la variable que posee los valores en JSON para que puedan ser utilizados con python de manera sencilla
values = json.dumps(values)
values = json.loads(values)
return [True, values]
def calc_stop_loss_sells(prices):
picos = []
for i in range(len(prices)):
# Si estamos en la primera vela o en la ultima, no hacemos nada, ya que no pueden ser un pico
if (i == 0 or i == (len(prices) - 1)):
pass
else:
if prices[i] > prices[i + 1] and prices[i] > prices[i - 1]:
picos.append(prices[i])
return picos[len(picos) - 1]
def calc_stop_loss_buys(prices):
picos = []
for i in range(len(prices)):
if (i == 0 or i == (len(prices) - 1)):
pass
else:
if prices[i] < prices[i + 1] and prices[i] < prices[i - 1]:
picos.append(prices[i])
return picos[len(picos) - 1]
def compararMedias():
ma50 = getMA50()
# Control de errores
if ma50[0] == False:
return -1
sleep(15)
ma200 = getMA200()
if ma200[0] == False:
return -1
# Si no ha ocurrido ningun error al realizar la peticion a la API.
if ma50[0] and ma200[0]:
# Si la media de 50 es menor que la media de 200, devuelvo que buscamos ventas.
if ma50[1]["value"] < ma200[1]["value"]:
# Devuelvo un 0 que significa que buscamos ventas.
return 0
elif ma50[1]["value"] > ma200[1]["value"]:
# Si no devuelvo un 1 que significa compras.
return 1
# Si las medias son iguales devuelvo un -1 porque no operamos.
return -1
def calc_take_profit(SL, open_price):
# open_price = get_klines(1)[1][1]
porcentaje_TP = (((SL * 100) / open_price) - 100) / 2
take_profit = ((100 - porcentaje_TP) / 100) * open_price
return take_profit
def result(stop_loss, take_profit, open_price, objetivo, acumulado):
# Calculo los % para mostrarlos luego segun el open price, el stop_loss y el take_profit
porcentaje_SL = 100 - ((stop_loss * 100) / open_price)
porcentaje_TP = ((take_profit * 100) / open_price) - 100
# Seteo una variable booleana a False para que hasta que no se haya terminado la operacion siga monitorizando si toca TP o SL.
exito = False
while not exito:
sleep(30)
# Obtengo la ultima vela que se ha formado constantemente hasta que el High o el Low superen al SL o al TP.
last_line = BinanceAPI.get_klines(1)
# Si estamos en compras el High debe ser superior al TP para ganar o el Low debe ser inferior al SL para perder.
if objetivo == 1:
# En este caso el High es superior o igual al TP, por lo que habriamos ganado.
if float(last_line[1][0][2]) >= take_profit:
message = "Operacion ganada" + "\U0001F680" + "!!!\n" + "% Realizado: " + str(porcentaje_TP)
acumulado[0] = acumulado[0] + float(porcentaje_TP)
TelegramBot.send_message(message)
exito = True
# En este caso el Low es inferior o igual al SL por lo que hubieramos perdido.
elif float(last_line[1][0][3]) <= stop_loss:
message = "Operacion perdida" + "\U0001F921" + "!!!\n" + "% Realizado: " + str(-porcentaje_SL)
acumulado[0] = acumulado[0] - float(porcentaje_SL)
TelegramBot.send_message(message)
exito = True
# Si estamos aqui es porque objetivo es igual a 0 lo que significa que estamos en ventas y es al reves.
else:
# En este caso el Low es inferior o igual al TP profit por lo que hubieramos ganado.
if float(last_line[1][0][3]) <= take_profit:
message = "Operacion ganada" + "\U0001F680" + "!!!\n" + "% Realizado: " + str(porcentaje_TP*-1)
acumulado[0] = acumulado[0] + float(porcentaje_TP*-1)
TelegramBot.send_message(message)
exito = True
# En este caso el High es superior o igual al SL por lo que hubieramos perdido
elif float(last_line[1][0][2]) >= stop_loss:
message = "Operacion perdida" + "\U0001F921" + "!!!\n" + "% Realizado: " + str(porcentaje_SL)
acumulado[0] = acumulado[0] + float(porcentaje_SL)
TelegramBot.send_message(message)
exito = True
message = "% Acumulado: " + str(acumulado[0]) + "\U0001F3A2"
return message
def banner():
custom_fig = Figlet(font='big')
print(custom_fig.renderText('BTC Trading Bot'))
print("Bot inicializado ....")
banner()
operamos = False
medias_comprobadas = False
saved_adx = False
pruebas = False
acumulado = [0]
objetivo = -1
imprimir = True
last_klines = None
while True:
try:
madrid = timezone('Europe/Madrid')
minutos = datetime.datetime.now(madrid).minute
# Comprobamos la posicion de las dos medias a las horas correspondientes.
if (minutos == 13) or (minutos == 28) or (minutos == 43) or (minutos == 58):
# -1 Medias Iguales, no hacemos nada
# 0 Buscamos ventas
# 1 Buscamos compras.
if not medias_comprobadas:
objetivo = compararMedias()
medias_comprobadas = True
if (minutos == 14) or (minutos == 29) or (minutos == 44) or (minutos == 59) and objetivo != -1:
if not saved_adx:
lista_DMI = getDMI(objetivo)[1]
saved_adx = True
if lista_DMI[0] > 25.00 > lista_DMI[1] and objetivo != -1:
operamos = True
last_klines = BinanceAPI.get_klines(15)
if imprimir:
print("")
print("[EMPEZAMOS OPERACION]\n")
print("Fecha: " + str(datetime.datetime.now(madrid)))
print("Objetivo: " + str(objetivo))
print("DI de la vela actual: " + str(lista_DMI[0]))
print("DI de la vela anterior: " + str(lista_DMI[1]))
print("[ESPERANDO AL FIN DEL CUARTO DE HORA PARA LANZAR LA ORDEN]")
print("")
message = "[EMPEZAMOS OPERACION] " + "\U000023F3"
TelegramBot.send_message(message)
imprimir = False
if (minutos == 15) or (minutos == 30) or (minutos == 45) or (minutos == 00):
if operamos and not BinanceAPI.existsOpenOrders():
open_price = float(last_klines[1][14][4])
aux = []
if objetivo == 1:
# Estamos en compras
for kline in last_klines[1]:
aux.append(float(kline[3]))
aux = aux[:len(aux)-1]
stop_loss = float(calc_stop_loss_buys(aux)) - 2.0
take_profit = round(calc_take_profit(stop_loss, open_price), 2)
print("")
print("[DATOS DE LA ORDEN DE COMPRA]")
print("Fecha: " + str(datetime.datetime.now(madrid)))
print("Precio de apertura: " + str(open_price))
print("Stop Loss: " + str(stop_loss))
print("Take Profit: " + str(take_profit))
print("")
cantidad_orden_contraria = BinanceAPI.buy(stop_loss, take_profit)
type = "COMPRA"
else:
# Estamos en ventas
for kline in last_klines[1]:
aux.append(float(kline[2]))
aux = aux[:len(aux) - 1]
stop_loss = float(calc_stop_loss_sells(aux)) + 2.0
take_profit = round(calc_take_profit(stop_loss, open_price), 2)
print("")
print("[DATOS DE LA ORDEN DE VENTA]")
print("Fecha: " + str(datetime.datetime.now(madrid)))
print("Precio de apertura: " + str(open_price))
print("Stop Loss: " + str(stop_loss))
print("Take Profit: " + str(take_profit))
print("")
cantidad_orden_contraria = BinanceAPI.sell(stop_loss, take_profit)
type = "VENTA"
message = "Empezamos operación de " + type + " con fecha: " + str(datetime.datetime.now(madrid)) + '\n' + \
"Precio de apertura de la operación: " + str(open_price) + '\n' + \
"STOP LOSS: " + str(stop_loss) + '\n' + \
"TAKE PROFIT: " + str(take_profit)
TelegramBot.send_message(message)
operamos = False
# Tener en cuenta que probablemente haya que cerrar las operaciones manualmente desde la testnet con la
# cuenta de daniel ya que no se cierran por defecto porque estamos cogiendo datos con otros precios
while BinanceAPI.existsOpenOrders():
respuesta = result(stop_loss, take_profit, open_price, objetivo, acumulado)
# Cancelamos la orden que falta. (ORDEN != POSICION)
BinanceAPI.cancelAllOrders(cantidad_orden_contraria, objetivo)
TelegramBot.send_message(respuesta)
saved_adx = False
medias_comprobadas = False
imprimir = True
except Exception as e:
print("[ERROR DE EJECUCION]\n")
print(e)
print("[FIN DE ERROR DE EJECUCION]\n")
message = "[" + "\U00002620" + "ERROR FATAL" + "\U00002620" + "] Mirar logs."
TelegramBot.send_message(message)
exit(1)