English version:
First of all, I inform you that I have three weeks reviewing Quantopian, also, I am new in the world of the financial market and in python. Therefore, I have great ignorance of many things in those fields.
On the other hand, my native language is Latin American Spanish, so for those who read this writing in English, I beg you to excuse my bad writing in English.
The point is that I am programming, in a date range of several months, the following:
1.- Only a daily short entry, which is placed three minutes after the market opens with the function called apertura_ordenes_venta. I am working with Apple stocks, just as an example.
2.- Every minute, through handle_data, it is checked whether the Take Profit or Stop Loss has occurred. In either case, the orders are closed.
I use the global variable cerrar_operacion to ensure that handle_data shows, once a day, when it occurs, that the Take Profit or the Stop Loss was reached. That is, during the day, after reaching Take Profit or Stopp Loss, nothing is done anymore.
3.- Five minutes before the market closes, through a function called terminando_el_dia, all open orders are closed.
Now, what I don't understand, and what I hope someone clarifies for me, is the following:
1.- Why, when running the Run Full Backtest, do many transactions appear every day, for example 18 transactions: several purchases and several sales?.Although I am only placing one sell order per day, three minutes after the market opens. And as I have programmed, a Take Profit or a Stop Loss should also occur. That is, I would expect only two transactions.
2.- Why sometimes the following situation occurs: “WARN Your order for -34745 shares of AAPL failed to fill by the end of day and was canceled”.
If I close all orders, 5 minutes before the market closes?
Below I show the code.
I would greatly appreciate if someone could help me clarify this situation.
Note: I'm very sorry but I couldn't add the code with attach.
Versión en español:
Primero que nada, les informo que tengo tres semanas revisando Quantopian, también, soy nuevo en el mundo del mercado financiero y en python. Por lo tanto, tengo gran desconocimiento de muchas cosas esos campos.
Por otro lado, mi idioma nativo es el español latinoamericano, entonces para quienes leen este escrito en inglés, les ruego sepan disculpar mi mala redacción en inglés.
El punto es que estoy programando, en un rango de fechas de varios meses, lo siguiente:
1.- Sólo una entrada en corto diaria, que se coloca tres minutos después que abre el mercado con la función que se llama apertura_ordenes_venta. Estoy trabajando con acciones de Apple, sólo como ejemplo.
2.- Cada minuto, a través de handle_data, se revisa si ha ocurrido el Take Profit o el Stop Loss. En cualquiera de los casos, se cierran las órdenes.
Utilizo la variable global cerrar_operacion para asegurar que handle_data muestre, una sola vez al día, cuando ocurre, que se alcanzó el Take Profit o el Stopp Loss. Es decir, que durante el día, después de alcanzar Take Profit o Stopp Loss no se hace más nada.
3.- Cinco minutos antes de que cierre el mercado, a través de una función que se llama terminando_el_dia, se cierran todas las órdenes abiertas.
Ahora, lo que no entiendo, y que espero que alguien me aclare, es lo siguiente:
1.- Por qué, al correr el Run Full Backtest, aparecen, cada día, muchas transacciones, por ejemplo 18 transacciones: varias compras y varias ventas?. Si yo, sólo estoy colocando una orden de venta al día, tres minutos después que abre el mercado. Y tal como tengo programado, debería ocurrir, también, un Take Profit o un Stop Loss. Es decir, yo esperaría sólo dos transacciones.
2.- Por qué a veces, ocurre la siguiente situación: WARN Your order for -34745 shares of AAPL failed to fill by the end of day and was canceled. Si yo cierro todas las órdenes, 5 minutos antes de que cierre el mercado?.
A continuación, muestro el código.
Mucho agradecería que alguien me pudiera ayudar a aclarar esta situación.
Nota: Lo siento mucho, pero no pude adjuntar el código con Attach.
2020-04-01 09:33 apertura_ordenes_venta:28 INFO Orden -1.0 AAPL Precio Actual 247.81 Precio Stop 247.79
2020-04-01 12:50 handle_data:57 INFO Take Profit -40353 AAPL Costo Base 247.19 Precio Actual 242.19 ratio 0.98
2020-04-02 09:33 apertura_ordenes_venta:28 INFO Orden -1.0 AAPL Precio Actual 239.15 Precio Stop 239.13
2020-04-02 10:09 handle_data:57 INFO Stop Loss -42542 AAPL Costo Base 237.93 Precio Actual 240.38 ratio 1.01
2020-04-03 09:33 apertura_ordenes_venta:28 INFO Orden -1.0 AAPL Precio Actual 244.17 Precio Stop 244.15
2020-04-06 09:33 apertura_ordenes_venta:28 INFO Orden -1.0 AAPL Precio Actual 250.33 Precio Stop 250.30
2020-04-06 09:51 handle_data:57 INFO Stop Loss -40573 AAPL Costo Base 249.89 Precio Actual 253.07 ratio 1.01
2020-04-07 09:33 apertura_ordenes_venta:28 INFO Orden -1.0 AAPL Precio Actual 268.75 Precio Stop 268.72
2020-04-07 09:56 handle_data:57 INFO Stop Loss -37285 AAPL Costo Base 267.17 Precio Actual 270.05 ratio 1.01
2020-04-08 09:33 apertura_ordenes_venta:28 INFO Orden -1.0 AAPL Precio Actual 262.89 Precio Stop 262.86
2020-04-08 11:13 handle_data:57 INFO Stop Loss -37730 AAPL Costo Base 262.30 Precio Actual 265.05 ratio 1.01
2020-04-09 09:33 apertura_ordenes_venta:28 INFO Orden -1.0 AAPL Precio Actual 268.09 Precio Stop 268.06
2020-04-13 09:33 apertura_ordenes_venta:28 INFO Orden -1.0 AAPL Precio Actual 268.00 Precio Stop 267.97
2020-04-13 14:57 handle_data:57 INFO Stop Loss -36560 AAPL Costo Base 267.28 Precio Actual 269.97 ratio 1.01
2020-04-14 09:33 apertura_ordenes_venta:28 INFO Orden -1.0 AAPL Precio Actual 279.34 Precio Stop 279.31
2020-04-14 16:00 WARN Your order for -34745 shares of AAPL failed to fill by the end of day and was canceled.
2020-04-15 09:33 apertura_ordenes_venta:28 INFO Orden -1.0 AAPL Precio Actual 282.82 Precio Stop 282.79
2020-04-15 13:19 handle_data:57 INFO Stop Loss -34317 AAPL Costo Base 282.37 Precio Actual 285.53 ratio 1.01
…
cerrar_operacion=0
def initialize(context):
context.stocks = [sid(24)]
context.profit_ratio = 0.98 # Límite, take profit
context.stop_ratio = 1.01 # stoploss
schedule_function(apertura_ordenes_venta, date_rules.every_day(),
time_rules.market_open(minutes=3))
# Cerrando posiciones antes del cierre del mercado
schedule_function(terminando_el_dia, date_rules.every_day(),
time_rules.market_close(minutes=5))
#####################################
Abrir posiciones en corto (ventas)####
#####################################
def apertura_ordenes_venta(context, data):
global cerrar_operacion
#log.info('Cerrar operación: {} '.format(cerrar_operacion))
cerrar_operacion=0
ordenes_abiertas = get_open_orders()
porcentaje = -1.0 # Porcentaje de la orden
for s in context.stocks:
if s in context.portfolio.positions: continue # Si hay una posición No abra órdenes
if s in ordenes_abiertas: continue # Si hay órdenes abiertas No abra otra.
precio_actual = data.current(s, 'price')
precio_stop = precio_actual * 0.9999 # Precio Stop
order_target_percent(s, porcentaje, style=StopOrder(precio_stop))
log.info('Orden {} {} Precio Actual {} Precio Stop {}'.format(
porcentaje, s.symbol, '%.2f' %precio_actual, '%.2f' % precio_stop ))
##########################################################################
Función que corre cada minuto con el fin de cerrar posiciones ####
##########################################################################
def handle_data(context, data):
#Ciclo a través de las posiciones para cerrar órdenes
# Se manejan sólo posiciones cortas en este ejemplo
global cerrar_operacion
for s in context.portfolio.positions:
# Omitir si ya existe una orden de cierre
ordenes_cerradas = 0
for o in get_open_orders(s): #Cancelar cada una de las órdenes abiertas del activo
if cancelar_ordenes_abiertas(context, o) in [0, 2]: #Si hay órdenes cerradas
ordenes_cerradas = 1
break
if ordenes_cerradas: continue
if not data.can_trade(s): continue # Cuando no se puede tradear
precio_actual = data.current(s, 'price')
costo_base = context.portfolio.positions[s].cost_basis
#log.info('Cerrar operación: {} '.format(cerrar_operacion))
if cerrar_operacion==0:
if precio_actual < costo_base * context.profit_ratio or precio_actual > costo_base * context.stop_ratio:
cantidad = context.portfolio.positions[s].amount
ratio = precio_actual / costo_base
mensaje = 'Stop Loss' if ratio > 1 else 'Take Profit'
log.info('{} {} {} Costo Base {} Precio Actual {} ratio {}'.format(
mensaje, cantidad, s.symbol, '%.2f' % costo_base, '%.2f' % precio_actual,
'%.2f' % ratio))
order_target(s, 0)
cerrar_operacion=1
#log.info('Cerrar operación: {} '.format(cerrar_operacion))
############################################################################
Cerrar (vendiendo) todas las órdenes abiertas al final de la jornada ###
############################################################################
def terminando_el_dia(context, data):
for s in context.portfolio.positions:
ordenes_abiertas = get_open_orders()
for s in ordenes_abiertas:
for o in ordenes_abiertas[s]:
cancel_order(o.id) # Cancelar todas las órdenes abiertas
# Si no hay orden de cierre, cierre.
if not get_open_orders(s):
order_target(s, 0)
##################################################################
Cerrar todas las órdenes abiertas al final de la jornada ###
##################################################################
def cancelar_ordenes_abiertas(c, o): # c = contexto o = objecto orden
# Si la orden se está cerrando, abriendo o crossover (short to long or reverse)
cantidad = c.portfolio.positions[o.sid].amount
if (cantidad - o.filled) * o.amount < 0: # close or x
if abs(o.amount) > abs(cantidad - o.filled):
if abs(cantidad) - abs(o.filled) < 0:
return 3 # crossed 0 shares and now opening
else: return 2 # x crossover
else: return 0 # close
else: return 1 # open