Exemple #1
0
    def worker_estado_op(self, op):
        if self.modotest:
            time.sleep(12)
            op[4] = Estado.OPERADA
        else:
            iol = Iol()
            estadoActual = iol.getOperacion(op[3])
            if estadoActual == "terminada":
                op[4] = Estado.OPERADA
            elif estadoActual == "cancelada":
                op[3] = "000"
                op[4] = Estado.ENPROCESO
            else:
                self.logging.info("Orden {} en estado {} ".format(
                    op[3], op[4]))

            self.logging.info("RUTEANDO GetOperacion # {}, estado: {}".format(
                op[3], estadoActual))
Exemple #2
0
    def worker_Vender(self, venta):
        ticker = venta[0]
        cantidad = venta[2]
        precio = venta[1]
        validez = datetime.now().strftime('%Y-%m-%d')

        if self.modotest:
            self.logging.info(" Vendiendo en modo test.")
            time.sleep(self.TIMEREFRESH)
            venta[4] = Estado.OPERADA
        else:
            iol = Iol()
            nroOrden = iol.vender(ticker, cantidad, precio, validez)
            if (nroOrden != "000"):
                venta[3] = nroOrden
                venta[4] = Estado.CURSANDO
                self.logging.info(
                    "RUTEANDO operación de venta NRO ORDEN: {}".format(
                        str(nroOrden)))
            else:
                self.logging.info(
                    "La operacion de venta {}, no fue recibida por el broker".
                    format(venta[0]))
Exemple #3
0
    def worker_Comprar(self, compra):
        ticker = compra[0]
        cantidad = compra[2]
        precio = compra[1]
        validez = datetime.now().strftime('%Y-%m-%d')

        if self.modotest:
            self.logging.info(" Comprando en modo test.")
            time.sleep(3)
            compra[4] = Estado.OPERADA
        else:
            iol = Iol()
            nroOrden = iol.comprar(ticker, cantidad, precio, validez)
            if (nroOrden != "000"):
                compra[3] = nroOrden
                compra[4] = Estado.CURSANDO
                self.logging.info(
                    "RUTEANDO operación de compra: NRO ORDEN: {}".format(
                        str(nroOrden)))
            else:
                self.logging.info(
                    "La operacion de compra {}, no fue recibida por el broker".
                    format(compra[0]))
Exemple #4
0
 def test_getOperacion(self):
     iol = Iol()
     nro = iol.getOperacion("25259360")
     print("Respuesta al GetOperacion: {}".format(nro))
     self.assertIsNotNone(nro)
Exemple #5
0
 def test_borrar(self):
     iol = Iol()
     nro = iol.borrarOperacion("25146843")
     print("Respuesta al borrado: {}".format(nro))
     self.assertIsNotNone(nro)
Exemple #6
0
 def test_vender(self):
     iol = Iol()
     nro = iol.vender("CRES", 2, 48,
                      datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
     print("Nro de operacion de venta: {}".format(nro))
     self.assertIsNotNone(nro)
Exemple #7
0
print(compras)

ventas = []
with open("./data/ventas" + fecha + ".dat", "rb") as f:
    ventas = pickle.load(f)
print("Cantidad ventas: " + str(len(ventas)))
#print(ventas)

compraTotal = float(0)
compraTotalVendidos = float(0)
saldoTotal = float(0)
saldoSinVender = float(0)
ventaTotal = float(0)
vendio = False
totalGanado = float(0)
iol = Iol()

for c in compras:
    vendio = False
    for v in ventas:
        if c[0] == v[0]:
            comprado = float(c[2] * c[1])
            vendido = float(v[2] * v[1])
            compraTotal = compraTotal + comprado
            compraTotalVendidos = compraTotalVendidos + comprado
            ventaTotal = ventaTotal + vendido
            print("\tCotiz compra: $ {0:.2f}".format(c[1]) +
                  " - Cotiz de venta: $ {0:.2f}".format(v[1]))
            costoCompra = iol.calculoCostoOp(comprado)

            ganancia = vendido - (comprado + costoCompra)
Exemple #8
0
    def __init__(self, lista, fecha):
        self.logger = self.loguear()
        self.logger.info("Iniciando Larva")

        self.fecha = fecha
        self.iol = Iol()
        self.getConfig()

        print("Minutos fin de periodo compras: {}".format(
            self.LIMITECOMPRA_MIN))
        self.dao = Dao(self.PATH)

        ### Indices [TICKER YAHOO, Desc, Cotiz cierre anterior, Cotiz actual]
        self.listaIndices.append(['^GSPC', "S&P 500", 0, 0])  ## S&P 500
        #self.listaIndices.append(['^IXIC',"NASDAQ", 0, 0]) ## NASDAQ
        #self.listaIndices.append(['^N225', "Nikkei", 0, 0]) ## Nikkei
        #self.listaIndices.append(['^IBEX',"IBEX", 0, 0]) ## IBEX
        #self.listaIndices.append(['^GDAXI',"DAX-ALEMANIA", 0, 0]) ## DAX PERFORMANCE-INDEX
        #self.listaIndices.append(['^HSI',"HANG SENG INDEX", 0, 0]) ## HANG SENG INDEX

        self.getPrincipalesIndices(fecha)
        print("Lista de indices.")
        print(self.listaIndices)

        if (self.MODOTEST != 1):
            self.lista = lista
            self.lista.append(['GGAL', 'GGAL.BA', 10, 0, 0, 0])
            self.lista.append(['YPF', 'YPFD.BA', 1, 0, 0, 0])
            self.lista.append(['BMA', 'BMA.BA', 10, 0, 0, 0])
            self.lista.append(['PAM', 'PAMP.BA', 25, 0, 0, 0])
            self.lista.append(['BBAR', 'BBAR.BA', 3, 0, 0, 0])
            self.lista.append(['CEPU', 'CEPU.BA', 10, 0, 0, 0])
            self.lista.append(['CRESY', 'CRES.BA', 10, 0, 0, 0])
            self.lista.append(['EDN', 'EDN.BA', 20, 0, 0, 0])
            self.lista.append(['SUPV', 'SUPV.BA', 5, 0, 0, 0])
            self.lista.append(['TEO', 'TECO2.BA', 5, 0, 0, 0])
            self.lista.append(['TGS', 'TGSU2.BA', 5, 0, 0, 0])
            self.lista.sort()
            self.cargar_cotiz(fecha)

            ## Guardo la lista
            self.dao.save(self.lista, "lista", self.fecha)
            ## Guardo la listaValoresActualesAcciones
            self.dao.save(self.listaValoresActualesAcciones,
                          "listaValoresActualesAcciones", self.fecha)
        else:  # MODO TEST
            self.dao.load(self.lista, "lista", self.fecha)
            print("Cantidad lista en Inicio: " + str(len(self.lista)))
            print(self.lista)
            ##Cargo listaValoresActualesAcciones desde archivo
            self.dao.load(self.listaValoresActualesAcciones,
                          "listaValoresActualesAcciones", self.fecha)
            print("Cantidad listaValoresActualesAcciones en Inicio: " +
                  str(len(self.lista)))
            print(self.listaValoresActualesAcciones)

        self.APERTURA = datetime.combine(fecha, self.HORARIOAPERTURA)
        self.logger.debug("Apertura: " + str(self.APERTURA))

        self.dolar_ccl_promedio = (self.calculo_ccl_AlCierreARG("GGAL.BA") +
                                   self.calculo_ccl_AlCierreARG("YPFD.BA") +
                                   self.calculo_ccl_AlCierreARG("BMA.BA") +
                                   self.calculo_ccl_AlCierreARG("PAMP.BA")) / 4

        ## Guardo fecha y ccl de ultimo cierre

        if not self.siExiste(self.listaccl, self.fechaUltimoCierreLocal):
            self.listaccl.append(
                [self.fechaUltimoCierreLocal, self.dolar_ccl_promedio])
        self.dao.load(self.listaccl, "listaccl", self.fecha)

        self.cargar_ValoresArbitrados()

        print(" CCL: " + str(self.dolar_ccl_promedio))
        self.dao.getComprasVentasfromFile(self.compras, self.ventas,
                                          self.fecha, self.iol)

        print("Fecha: " + self.fecha.strftime('%d/%m/%Y %H:%M:%S'))
        self.logger.info("INICIANDO LARVA " +
                         self.fecha.strftime('%d/%m/%Y %H:%M:%S'))
        print("\n\n**CCL al cierre anterior, " +
              str(self.fechaUltimoCierreLocal) +
              ", (GGAL, YPFD, BMA, PAMP) Promedio: ${0:.2f}".format(
                  self.dolar_ccl_promedio))
        self.logger.info(
            "\n\n**CCL al cierre anterior: (GGAL, YPFD, BMA, PAMP) Promedio: {0:.2f}"
            .format(self.dolar_ccl_promedio))
Exemple #9
0
class AADR(object):
    lista = [
    ]  ##    ( TICKER EXTRANGERO, TICKER LOCAL, FACTOR, COTIZ ADR CIERRE ANTEIOR, COTIZ LOCAL CIERRE ANTERIOR, VALOR ARBITRADO) ##Lista que mantiene cotizaciónes al cierre anterior ##
    compras = [
    ]  ##  ( TICKER, VALOR, CANTIDAD, NROOPERACION, Estado(Enum), TIMESTAMP, VALORVENTAMINVALORVENTAMIN)
    ventas = [
    ]  ##   ( TICKER, VALOR, CANTIDAD, NROOPERACION, Estado(Enum), TIMESTAMP)
    listaValoresActualesAcciones = [
    ]  ## TICKER, ULTIMOPRECIO, punta_cantCompra, punta_precioCompra, punta_cantVenta, punta_precioVenta, TIMESTAMP)
    listaValoresActualesAdrs = [
    ]  ## TICKER, ULTIMOPRECIO, punta_cantCompra, punta_precioCompra, punta_cantVenta, punta_precioVenta, TIMESTAMP)
    listaccl = []  ##Lista de historicos CCL.
    listaIndices = []

    fechaUltimoCierreLocal = ""
    fechaUltimoCierreAdr = ""
    TIMEREFRESH = 10  ## Valor por defecto. Toma el valor del archivo config.json
    #MONTOCOMPRA = 2000 # SOLO SE COMPRA de a 1 papel
    GANANCIAPORCENTUAL = 1  #Constante que defije objetivo de ganancia relativa porcentual
    DIFPORCENTUALMINCOMPRA = GANANCIAPORCENTUAL + 0.4  #Minima diferencia con el valor arbitrado par considerarlo en la compra.
    PORCENTUALINDICES = 0.2  # Porcentaje de indice de otros mercados que tiene que superar para poder habilitar la compra.
    LIMITECOMPRA_MIN = 15  # Minutos desde apertura
    MINUTEGRADIENTEVENTA = 30
    PERIODOVENTAFORZADAMIN = 300  ## 16hs comienza el horario de venta a costo.
    enPeriodoCompra = True
    FINVENTAS = False
    #GANANCIA = float(0)

    MODOTEST = 0
    CONRUTEO = False  ## Por parametros
    HORARIOAPERTURA = time(hour=11, minute=00, second=0)
    PORCENTUALINDICES = 0.2

    def __init__(self, lista, fecha):
        self.logger = self.loguear()
        self.logger.info("Iniciando Larva")

        self.fecha = fecha
        self.iol = Iol()
        self.getConfig()

        print("Minutos fin de periodo compras: {}".format(
            self.LIMITECOMPRA_MIN))
        self.dao = Dao(self.PATH)

        ### Indices [TICKER YAHOO, Desc, Cotiz cierre anterior, Cotiz actual]
        self.listaIndices.append(['^GSPC', "S&P 500", 0, 0])  ## S&P 500
        #self.listaIndices.append(['^IXIC',"NASDAQ", 0, 0]) ## NASDAQ
        #self.listaIndices.append(['^N225', "Nikkei", 0, 0]) ## Nikkei
        #self.listaIndices.append(['^IBEX',"IBEX", 0, 0]) ## IBEX
        #self.listaIndices.append(['^GDAXI',"DAX-ALEMANIA", 0, 0]) ## DAX PERFORMANCE-INDEX
        #self.listaIndices.append(['^HSI',"HANG SENG INDEX", 0, 0]) ## HANG SENG INDEX

        self.getPrincipalesIndices(fecha)
        print("Lista de indices.")
        print(self.listaIndices)

        if (self.MODOTEST != 1):
            self.lista = lista
            self.lista.append(['GGAL', 'GGAL.BA', 10, 0, 0, 0])
            self.lista.append(['YPF', 'YPFD.BA', 1, 0, 0, 0])
            self.lista.append(['BMA', 'BMA.BA', 10, 0, 0, 0])
            self.lista.append(['PAM', 'PAMP.BA', 25, 0, 0, 0])
            self.lista.append(['BBAR', 'BBAR.BA', 3, 0, 0, 0])
            self.lista.append(['CEPU', 'CEPU.BA', 10, 0, 0, 0])
            self.lista.append(['CRESY', 'CRES.BA', 10, 0, 0, 0])
            self.lista.append(['EDN', 'EDN.BA', 20, 0, 0, 0])
            self.lista.append(['SUPV', 'SUPV.BA', 5, 0, 0, 0])
            self.lista.append(['TEO', 'TECO2.BA', 5, 0, 0, 0])
            self.lista.append(['TGS', 'TGSU2.BA', 5, 0, 0, 0])
            self.lista.sort()
            self.cargar_cotiz(fecha)

            ## Guardo la lista
            self.dao.save(self.lista, "lista", self.fecha)
            ## Guardo la listaValoresActualesAcciones
            self.dao.save(self.listaValoresActualesAcciones,
                          "listaValoresActualesAcciones", self.fecha)
        else:  # MODO TEST
            self.dao.load(self.lista, "lista", self.fecha)
            print("Cantidad lista en Inicio: " + str(len(self.lista)))
            print(self.lista)
            ##Cargo listaValoresActualesAcciones desde archivo
            self.dao.load(self.listaValoresActualesAcciones,
                          "listaValoresActualesAcciones", self.fecha)
            print("Cantidad listaValoresActualesAcciones en Inicio: " +
                  str(len(self.lista)))
            print(self.listaValoresActualesAcciones)

        self.APERTURA = datetime.combine(fecha, self.HORARIOAPERTURA)
        self.logger.debug("Apertura: " + str(self.APERTURA))

        self.dolar_ccl_promedio = (self.calculo_ccl_AlCierreARG("GGAL.BA") +
                                   self.calculo_ccl_AlCierreARG("YPFD.BA") +
                                   self.calculo_ccl_AlCierreARG("BMA.BA") +
                                   self.calculo_ccl_AlCierreARG("PAMP.BA")) / 4

        ## Guardo fecha y ccl de ultimo cierre

        if not self.siExiste(self.listaccl, self.fechaUltimoCierreLocal):
            self.listaccl.append(
                [self.fechaUltimoCierreLocal, self.dolar_ccl_promedio])
        self.dao.load(self.listaccl, "listaccl", self.fecha)

        self.cargar_ValoresArbitrados()

        print(" CCL: " + str(self.dolar_ccl_promedio))
        self.dao.getComprasVentasfromFile(self.compras, self.ventas,
                                          self.fecha, self.iol)

        print("Fecha: " + self.fecha.strftime('%d/%m/%Y %H:%M:%S'))
        self.logger.info("INICIANDO LARVA " +
                         self.fecha.strftime('%d/%m/%Y %H:%M:%S'))
        print("\n\n**CCL al cierre anterior, " +
              str(self.fechaUltimoCierreLocal) +
              ", (GGAL, YPFD, BMA, PAMP) Promedio: ${0:.2f}".format(
                  self.dolar_ccl_promedio))
        self.logger.info(
            "\n\n**CCL al cierre anterior: (GGAL, YPFD, BMA, PAMP) Promedio: {0:.2f}"
            .format(self.dolar_ccl_promedio))

    ### Varialiones de los principales indices.
    def getPrincipalesIndices(self, fecha):
        start = fecha - timedelta(days=4)
        end = fecha

        for campo in self.listaIndices:
            ind = campo[0]
            df = yf.download(ind,
                             start=start.strftime('%Y-%m-%d'),
                             end=end.strftime('%Y-%m-%d'))
            try:
                cierreAnterior = float(
                    df.drop(fecha.date()).tail(1)['Close'].values[0])
            except KeyError:
                cierreAnterior = float(df.tail(1)['Close'].values[0])

            campo[2] = cierreAnterior

            fin = float(
                yf.download(ind,
                            period=fecha.strftime('%Y-%m-%d'),
                            interval='1m').tail(1)['Close'].values[0])
            campo[3] = fin

            prop = ((fin - cierreAnterior) / fin) * 100
            self.logger.info(
                campo[1] + " - " + campo[0] +
                ": Variacion ultimo cierre: {0:.2f} %".format(prop))

    ## Carga en la lista las cotizaciónes actuales de los indices
    def getCotizActualIndices(self, fecha):
        for campo in self.listaIndices:
            fin = float(
                yf.download(campo[0],
                            period=fecha.strftime('%Y-%m-%d'),
                            interval='1m').tail(1)['Close'].values[0])
            campo[3] = fin

    ## Toma configuracion de un archivo
    def getConfig(self):
        with open('config.json', 'r') as file:
            config = json.load(file)
        self.PATH = config['DEFAULT']['PATH']
        self.TIMEREFRESH = config['DEFAULT']['TIMEREFRESH']
        self.PERIODOVENTAFORZADAMIN = config['DEFAULT'][
            'PERIODOVENTAFORZADAMIN']
        self.GANANCIAPORCENTUAL = config['DEFAULT']['GANANCIAPORCENTUAL']
        self.PORCENTUALINDICES = config['DEFAULT']['PORCENTUALINDICES']
        self.LIMITECOMPRA_MIN = config['DEFAULT']['LIMITECOMPRA_MIN']
        if config['DEFAULT']['CONRUTEO'] == 1:
            self.CONRUTEO = True

    ## LOGGER
    def loguear(self):
        handler = logging.handlers.WatchedFileHandler(
            os.environ.get("LOGFILE", "larva.log"))
        #handler = logging.StreamHandler()
        formatter = logging.Formatter(
            ' %(asctime)s - %(threadName)s - %(funcName)s - %(levelname)s - %(message)s '
        )
        handler.setFormatter(formatter)
        root = logging.getLogger("logueador")
        root.setLevel(os.environ.get("LOGLEVEL", "INFO"))
        root.addHandler(handler)

        return root

    ##
    # Metodo que te carga el valor arbitrado de todos los tickers en la lista.
    def cargar_ValoresArbitrados(self):
        for campo in self.lista:
            valor_arbitrado = float(
                self.calculo_valor_arbitrado(campo[1],
                                             self.dolar_ccl_promedio))
            campo[5] = valor_arbitrado

    ## Carga cotizaciones del cierre anterior en lista.
    ## ( TICKER EXTRANGERO, TICKER LOCAL, FACTOR, COTIZ ADR CIERRE ANTEIOR, COTIZ LOCAL CIERRE ANTERIOR, VALOR ARBITRADO)
    def cargar_cotiz(self, fecha):
        self.logger.debug('Cargando cotizaciones ultimo cierre.')
        #lista_aux=[]
        start = fecha - timedelta(days=5)
        end = fecha
        for campo in self.lista:
            ## Tomo la ultima cotización local.
            local_ca = 0
            try:
                pd_local_aux = yf.download(campo[1],
                                           start=start.strftime('%Y-%m-%d'),
                                           end=end.strftime('%Y-%m-%d'),
                                           interval="1d")
                pd_local = pd_local_aux.drop(fecha.date()).tail(1)
            except KeyError:
                self.logger.debug("No se pudo borrar el dia de hoy. " +
                                  campo[1])
                pd_local = pd_local_aux.tail(1)
            if not pd_local.empty:
                local_ca = pd_local['Close'].values[0]
                np_date = pd_local.index.values[0]
                self.fechaUltimoCierreLocal = numpy.datetime_as_string(
                    np_date, "D")
                self.logger.debug(
                    self.fechaUltimoCierreLocal + " - " + campo[1] +
                    " C. Loc ULT CIERRE {0:.2f}".format(local_ca))

            ## Tomo la ultima cotizacion ADR.
            adr_ca = 0
            try:
                pd_adr_aux = yf.download(campo[0],
                                         start=start.strftime('%Y-%m-%d'),
                                         end=end.strftime('%Y-%m-%d'),
                                         interval="1d")
                pd_adr = pd_adr_aux.drop(fecha.date()).tail(1)
            except KeyError:
                self.logger.debug("No se pudo borrar el dia de hoy. " +
                                  campo[0])
                pd_adr = pd_adr_aux.tail(1)
            if not pd_adr.empty:
                adr_ca = pd_adr['Close'].values[0]
                np_date = pd_adr.index.values[0]
                self.fechaUltimoCierreAdr = numpy.datetime_as_string(
                    np_date, "D")
                self.logger.debug(self.fechaUltimoCierreAdr + " - " +
                                  campo[0] +
                                  " C. ADR ULT CIERRE {0:.2f}".format(adr_ca))

            ##Con esta linea me traigo el ADR del mismo dia del local
            #pd_adr = yf.download(campo[0], start=numpy.datetime_as_string(np_date, "D"), interval="1d").head(1)

            campo[3] = adr_ca
            campo[4] = local_ca
        return None

    ### Metodo que calcula es CCL al ultimo cierre.
    ##
    def calculo_ccl_AlCierreARG(self, tickerlocal):
        cotizadrf = 0
        cotizlocalf = 0
        factor = 1
        for campo in self.lista:
            if (campo[1] == tickerlocal):
                factor = campo[2]
                cotizlocalf = campo[4]
                cotizadrf = campo[3]
                break

        resultado = (float(cotizlocalf) / (float(cotizadrf) / float(factor)))
        self.logger.debug(tickerlocal + " C. ADR: {0:.2f}".format(cotizadrf) +
                          " C. Loc: {0:.2f}".format(cotizlocalf) + ' Fac.: ' +
                          str(factor) + " CCL: {0:.2f}".format(resultado))
        return resultado

    def calculo_valor_arbitrado(self, tickerlocal, dolar_ccl_promedio):
        cotizadrf = 0
        factor = 0
        for campo in self.lista:
            if (campo[1] == tickerlocal):
                cotizadrf = campo[3]
                factor = campo[2]
                break

        return (cotizadrf / float(factor)) * float(dolar_ccl_promedio)

    ## TICKER, ULTIMOPRECIO, punta_cantCompra, punta_precioCompra, punta_cantVenta, punta_precioVenta, TIMESTAMP)
    def getTodasLasCotizaciones(self):
        body = self.iol.getCotizAccionesTodas()

        if body == "":
            return 0

        l = []
        for campo in self.lista:
            for campoBody in body['titulos']:
                ticker = campo[1].split(".")[0]
                if ticker == campoBody['simbolo']:
                    puntas = campoBody['puntas']
                    punta_cantCompra = 0
                    punta_precioCompra = 0
                    punta_cantVenta = 0
                    punta_precioVenta = 0
                    try:
                        punta_cantCompra = puntas['cantidadCompra']
                        punta_precioCompra = puntas['precioCompra']
                        punta_cantVenta = puntas['cantidadVenta']
                        punta_precioVenta = puntas['precioVenta']
                    except:
                        self.logger.warning(
                            "Lista de puntas incompleta. Se cargan valores en Cero. "
                        )

                    ahora = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
                    ultimoPrecio = campoBody['ultimoPrecio']
                    l.append((ticker, ultimoPrecio, punta_cantCompra,
                              punta_precioCompra, punta_cantVenta,
                              punta_precioVenta, ahora))
                    break
        #self.logger.debug("Se cargaron todas las cotizaciónes desde IOL, total "+str(len(l)))
        self.listaValoresActualesAcciones = l

    ## ADRs
    ## TICKER, ULTIMOPRECIO, punta_cantCompra, punta_precioCompra, punta_cantVenta, punta_precioVenta, TIMESTAMP)
    def getTodasLasCotizacionesADRs(self):
        body = self.iol.getCotizAdrsTodas()
        l = []
        for campo in self.lista:
            for campoBody in body['titulos']:
                ticker = campo[1].split(".")[0]
                if ticker == campoBody['simbolo']:
                    puntas = campoBody['puntas']
                    punta_cantCompra = 0
                    punta_precioCompra = 0
                    punta_cantVenta = 0
                    punta_precioVenta = 0
                    try:
                        punta_cantCompra = puntas['cantidadCompra']
                        punta_precioCompra = puntas['precioCompra']
                        punta_cantVenta = puntas['cantidadVenta']
                        punta_precioVenta = puntas['precioVenta']
                    except:
                        self.logger.warning("Lista de puntas incompleta. ")

                    ahora = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
                    ultimoPrecio = campoBody['ultimoPrecio']
                    l.append((ticker, ultimoPrecio, punta_cantCompra,
                              punta_precioCompra, punta_cantVenta,
                              punta_precioVenta, ahora))
                    break
        self.listaValoresActualesAdrs = l

    ## devuelve: ULTIMOPRECIO, punta_precioCompra, punta_cantCompra, punta_precioVenta, punta_cantVenta
    def getCotizacion(self, tickerlocal):
        for campo in self.listaValoresActualesAcciones:
            if campo[0] == tickerlocal:
                return [campo[1], campo[3], campo[2], campo[5], campo[4]]
        self.logger.warning("NO encontro el ticker: " + tickerlocal)
        return [0, 0, 0, 0, 0]

    ## Devuelve True si los indices cumplen con la condicion
    # TODO: por ahora solo tomo el SP500 como indice referencia.
    def condicionIndicesMundiales(self):
        propSP500 = self.calculoPropIndice()

        if propSP500 >= self.PORCENTUALINDICES:
            self.logger.info(
                "Se habilita la compra. SP500 {0:.2f}%".format(propSP500) +
                " mayor a: {0:.2f}% ".format(self.PORCENTUALINDICES))
            return True
        else:
            self.logger.info(
                "Bloqueo la compra. SP500 {0:.2f}% ".format(propSP500))
            return False

    def calculoPropIndice(self):
        return ((self.listaIndices[0][3] - self.listaIndices[0][2]) /
                self.listaIndices[0][3]) * 100

    ## Devuelve true si hay compras pendientes de venta. falso en caso contrario
    def isComprasPendientes(self):
        for campo in self.compras:
            if campo[4] != Estado.OPERADA: return True
        return False

    ## Metodo que devuelve True en caso de estar dentro del periodo de compra
    def isHorarioCompra(self):
        now = datetime.now()
        minutosTranscurridos = (now - self.APERTURA).seconds / 60

        if now <= self.APERTURA:
            print("La rueda no abrio.")
            return True

        #if 0 <= minutosTranscurridos and (minutosTranscurridos <= self.LIMITECOMPRA_MIN):
        if (minutosTranscurridos <= self.LIMITECOMPRA_MIN):
            self.logger.info(" Tiempo de compra: " + str(minutosTranscurridos))
            return True
        else:
            self.logger.info(" Termino periodo de compra. ")
            return False

    ## Metodo que permite hacer seguimietno ONLINE de ARB.
    def larva(self):
        fecha = self.fecha
        threadvendedor = threading.Thread(target=self.worker_venta,
                                          name="HiloVentas")
        threadvendedor.start()

        self.logger.debug("Arranca larva: ")

        self.enPeriodoCompra = self.isHorarioCompra()

        ## Inicio Routing
        if (self.CONRUTEO):
            r = RoutingOrder(self.compras, self.ventas, False, self.logger,
                             self.enPeriodoCompra)
        ###
        ### Bucle principal ##############################################################
        while (True):
            ahora = self.fecha.strftime('%d/%m/%Y %H:%M:%S')
            print("\tFecha: " + ahora)

            self.getConfig()

            print(Fore.BLUE + "\nCompras: " + str(self.compras) + Fore.RESET)
            self.getTodasLasCotizaciones()

            ## Actualizo los valores actuales de los indices.
            self.getCotizActualIndices(fecha)

            ## Actualizo horario de compra
            self.enPeriodoCompra = self.isHorarioCompra()

            if self.enPeriodoCompra:
                if self.condicionIndicesMundiales():
                    for tt in self.lista:  ## ITERO POR TICKER
                        tickerlocal = tt[1].split(".")[0]
                        local_up, punta_precioCompra, punta_cantidadCompra, punta_precioVenta, punta_cantidadVenta = self.getCotizacion(
                            tickerlocal)

                        valor_arbi = float(tt[5])
                        cotizlocalf = float(local_up)

                        diferencia = float(valor_arbi) - float(cotizlocalf)
                        variacion = float(
                            (diferencia) * 100) / float(cotizlocalf)

                        if (variacion >= self.DIFPORCENTUALMINCOMPRA):
                            ## Imprimo ticker con posibilidad de compra.
                            print(Fore.BLUE + tickerlocal +
                                  " => LOCAL: ${0:.2f}".format(cotizlocalf) +
                                  " - ARBITRADO: ${0:.2f}".format(valor_arbi) +
                                  " - VAR: {0:.2f}%".format(variacion) +
                                  Fore.RESET)

                            self.logger.info(
                                tickerlocal +
                                " * LOCAL: ${0:.2f}".format(cotizlocalf) +
                                " - ARBITRADO: ${0:.2f}".format(valor_arbi) +
                                " - VAR: {0:.2f}%".format(variacion))
                            ##################
                            ### Proceso Compra
                            valorCompraMax, valorVentaMin = self.calculoValoresCompraYVenta(
                                tickerlocal, cotizlocalf, valor_arbi)

                            if valorCompraMax != 0 and punta_precioVenta != 0 and valorCompraMax >= punta_precioVenta and not self.siExiste(
                                    self.compras, tickerlocal):
                                #cantidad = self.MONTOCOMPRA // cotizlocalf
                                cantidad = 1
                                print(Fore.GREEN +
                                      " AVISO: Comprar: {0:.2f}".format(
                                          cantidad) +
                                      " - PUNTAS:  *VENTA - Cant: {0:.2f}".
                                      format(punta_cantidadVenta) +
                                      ", valor: {0:.2f}".format(
                                          punta_precioVenta) +
                                      " *COMPRA - Cant: {0:.2f}".format(
                                          punta_cantidadCompra) +
                                      ", valor: {0:.2f}".format(
                                          punta_precioCompra) + Fore.RESET)
                                self.compra(tickerlocal, cotizlocalf, cantidad,
                                            valorVentaMin)
                        else:
                            print(tickerlocal +
                                  " => LOCAL: ${0:.2f}".format(cotizlocalf) +
                                  " - ARBITRADO: ${0:.2f}".format(valor_arbi) +
                                  " - VAR: {0:.2f}%".format(variacion))
                            self.logger.info(
                                tickerlocal +
                                " * LOCAL: ${0:.2f}".format(cotizlocalf) +
                                " - ARBITRADO: ${0:.2f}".format(valor_arbi) +
                                " - VAR: {0:.2f}%".format(variacion))
                    ## TIEMPO DEL CICLO
                    print(Fore.RED +
                          "\n ...Hilo ppal(de compra) en ejecucion..." +
                          datetime.now().strftime('%d/%m/%Y %H:%M:%S') +
                          Fore.RESET)
                else:
                    print("Se Bloquea la compra. SP500 {0:.2f}%".format(
                        self.calculoPropIndice()) +
                          " menor a: {0:.2f}% ".format(self.PORCENTUALINDICES))
            else:
                print("Termino periodo de compra. ")
                if not self.isComprasPendientes() and self.MODOTEST == 0:
                    self.logger.info("**FIN HILO COMPRAS**")
                    print("** FIN HILO COMPRAS ** ")
                    self.FINVENTAS = True
                    return

            ti.sleep(self.TIMEREFRESH)

    ## Metodo que implementa el Hilo de Venta
    def worker_venta(self):
        ## Hilo de VENTA
        ## Recorre lista de compras
        self.logger.debug("Inicio worker venta")
        while (True):
            if (len(self.compras) == 0):
                self.logger.debug("NO HAY COMPRAS HECHAS")
            else:
                self.logger.debug(
                    "Compras pendientes de venta: {0:.2f}".format(
                        float(len(self.compras) - len(self.ventas))))
                self.xventa()

            self.logger.info("...Hilo venta en ejecucion... " +
                             datetime.now().strftime('%d/%m/%Y %H:%M:%S'))
            if self.FINVENTAS and not self.isComprasPendientes():
                self.logger.info("**FIN HILO VENTAS**")
                print("** FIN HILO VENTAS ** ")
                return
            ti.sleep(self.TIMEREFRESH)

    ## Metodo que compara el objetivo de venta con el precio de la punta de compra. Si es menor manda la compra.
    def xventa(self):
        for compra in self.compras:
            if compra[4] == Estado.OPERADA and not self.seVendio(compra[0]):
                local_up, punta_precioCompra, punta_cantidadCompra, punta_precioVenta, punta_cantidadVenta = self.getCotizacion(
                    compra[0])

                ##Logica que tiene en cuenta el tipo que hace que esta comprado y cambia el ValorMinVenta
                self.gradientePrecioVenta(compra)
                self.logger.info(
                    "Ticker: " + compra[0] +
                    " Punta de compra: $ {0:.2f}".format(punta_precioCompra) +
                    " Objetivo: $ {0:.2f}".format(compra[6]))

                if punta_precioCompra != 0 and punta_precioCompra >= compra[6]:
                    print(Fore.BLUE + "\tObjetivo Venta CUMPLIDO: " +
                          compra[0] +
                          " Valor: {0:.2f}".format(punta_precioCompra) +
                          Fore.RESET)
                    self.logger.info(
                        "Objetivo Venta CUMPLIDO: " + compra[0] +
                        " Valor: {0:.2f}".format(punta_precioCompra))
                    if (punta_cantidadCompra < compra[2]):
                        self.logger.debug(
                            "La cantidad de la punta de compra es menor a la cantidad que se quiere vender. VER"
                        )
                    self.vender(compra, punta_precioCompra)

    ## Metodo que agrega a la
    def vender(self, compra, valor):
        ticker = compra[0]
        cantidad = compra[2]
        if not self.siExiste(self.ventas, ticker):
            self.logger.debug("Envio VENTA: " + ticker +
                              " Cantidad: {0:.2f}".format(cantidad) +
                              " Valor: {0:.2f}".format(valor))
            self.agregarVenta(ticker, valor, cantidad)
            print(Fore.GREEN + "\tVenta Finalizada: " + ticker +
                  " Valor: {0:.2f}".format(valor) +
                  " Cantidad: {0:.2f}".format(cantidad) + Fore.RESET)
        else:
            self.logger.debug("Esta venta ya fue hecha.")
            ##TODO: Ver como hacer para borrar una orden de venta a la cual hay que cambiarle el valor.

        return None

        ## Agrega la venta a la lista. Actualiza el estado de la compra y persiste en disco.
    def agregarVenta(self, ticker, valor, cantidad):
        ahora = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        self.ventas.append(
            [ticker, valor, cantidad, "000", Estado.ENPROCESO, ahora])
        self.actualizarVentas(self.ventas, self.fecha)

    ## En funcion del tiempo que hace que esta comprado el papel baja el valorMinVenta.
    def gradientePrecioVenta(self, compra):
        ahora = datetime.now()
        horarioCompra = compra[5]

        difCompra = ahora - datetime.strptime(horarioCompra,
                                              "%Y-%m-%d %H:%M:%S")
        valorCompra = compra[1]
        costoCompra = valorCompra + self.iol.calculoCostoOp(valorCompra)
        difObjetivo = compra[6] - costoCompra
        descuento = difObjetivo / 3

        #self.logger.info(campo[0]+" Costo TOTAL compra: $ {0:.2f} (incluye costos broker)".format(costoCompra))
        nuevoValor = compra[6]

        if self.MINUTEGRADIENTEVENTA <= (difCompra.seconds / 60) and (
                difCompra.seconds / 60) < (2 * self.MINUTEGRADIENTEVENTA):
            nuevoValor = compra[6] - descuento
            self.logger.info(
                compra[0] +
                " Ejecuto Gradiente N1, decuento: ${0:.2f}".format(descuento) +
                " Nuevo ValorVentaMin: ${0:.2f}".format(nuevoValor) +
                " (anterior: ${0:.2f})".format(compra[6]))

        elif (2 * self.MINUTEGRADIENTEVENTA) <= (difCompra.seconds / 60) and (
                difCompra.seconds / 60) <= (4 * self.MINUTEGRADIENTEVENTA):
            nuevoValor = compra[6] - (2 * descuento)
            self.logger.info(
                compra[0] +
                " Ejecuto Gradiente N2, decuento: ${0:.2f}".format(2 *
                                                                   descuento) +
                " Nuevo ValorVentaMin: ${0:.2f}".format(nuevoValor) +
                " (anterior: ${0:.2f})".format(compra[6]))

        elif (4 * self.MINUTEGRADIENTEVENTA) < (difCompra.seconds / 60):
            nuevoValor = compra[6] - (3 * descuento)
            self.logger.info(
                compra[0] +
                " Ejecuto Gradiente N3, decuento: ${0:.2f}".format(3 *
                                                                   descuento) +
                " Nuevo ValorVentaMin: ${0:.2f}".format(nuevoValor) +
                " (anterior: ${0:.2f})".format(compra[6]))

        ## 16:00 intento vender al costo de compra.
        if (ahora >= self.APERTURA):
            difAperturaMin = (ahora - self.APERTURA).seconds / 60
        else:
            difAperturaMin = 0
        self.logger.info(
            " Minutos desde la apertura: {0:.2f} ".format(difAperturaMin))

        if self.PERIODOVENTAFORZADAMIN <= difAperturaMin and difAperturaMin < 345:
            nuevoValor = costoCompra
            self.logger.info(
                compra[0] +
                " Ejecuto Gradiente Final, Nuevo ValorVentaMin: ${0:.2f}".
                format(nuevoValor))
        '''
        ## Gradientes con perdida.
        ## 16:45

        if 345 <= difAperturaMin and difAperturaMin < 350:
            descuento5 = costoCompra * 5 / 100
            totalDescuento5 = (costoCompra-descuento5) * compra[2]
            if totalDescuento5 <= self.ganancia:
                nuevoValor = costoCompra - descuento5
                self.logger.info(compra[0] + " Ejecuto Gradiente c/Perdida, Nuevo ValorVentaMin: ${0:.2f}".format(nuevoValor))
            else: self.logger.info(compra[0] + " Gradiente c/Perdida 16:45 sin saldo")
        ## 16:50
        if 350 <= difAperturaMin and difAperturaMin < 355:
            descuento10 = costoCompra * 10 / 100
            totalDescuento10 = (costoCompra - descuento10) * compra[2]
            if totalDescuento10 <= self.ganancia:
                nuevoValor = costoCompra - descuento10
                self.logger.info(compra[0] + " Ejecuto Gradiente c/Perdida, Nuevo ValorVentaMin: ${0:.2f}".format(nuevoValor))
            else: self.logger.info(compra[0] + " Gradiente c/Perdida 16:50 sin saldo")

        ## 16:55
        if 355 <= difAperturaMin:
            descuento15 = costoCompra * 15 / 100
            totalDescuento15 = (costoCompra - descuento15) * compra[2]
            if totalDescuento15 <= self.ganancia:
                nuevoValor = costoCompra - descuento15
                self.logger.info(compra[0] + " Ejecuto Gradiente c/Perdida, Nuevo ValorVentaMin: ${0:.2f}".format(nuevoValor))
            else: self.logger.info(compra[0] + " Gradiente c/Perdida 16:55 sin saldo")
        '''
        if (nuevoValor != compra[6]):
            compra[6] = nuevoValor
            self.actualizarCompras()

        return None

    ## Calcula el punto medio entre el valor y el arbitrado y se mueve 0,5 para cada lado
    def calculoValoresCompraYVenta(self, ticker, valor, valorArbitrado):
        medio = (valorArbitrado + valor) / 2
        valorCompraMax = medio - (medio * (self.GANANCIAPORCENTUAL / 2) / 100)
        valorVentaMin = medio + (medio * (self.GANANCIAPORCENTUAL / 2) / 100)

        self.logger.debug(
            ticker + " COTIZ ACTUAL: $ {0:.2f}".format(valor) +
            "\t Valor compra Maximo {0:.2f}".format(valorCompraMax) +
            " -- Valor venta Minimo {0:.2f}".format(valorVentaMin))

        return [valorCompraMax, valorVentaMin]

    ## Orden que envia a comprar y agrega a la lista de operaciones pendientes.
    def compra(self, ticker, valor, cantidad, valorVentaMin):
        self.logger.debug("COMPRA: " + ticker +
                          " Cantidad: {0:.2f}".format(cantidad) +
                          " Valor: {0:.2f}".format(valor))
        self.agregarCompra(ticker, valor, cantidad, valorVentaMin)
        costoOperacion = self.iol.calculoCostoOp(valor)
        self.logger.info("Costo compra: {0:.2f}".format(costoOperacion))
        print("Comprado!!!")

    def seVendio(self, ticker):
        for tt in self.ventas:
            if (tt[0] == ticker and tt[4] == Estado.OPERADA): return True
        return False

    ## Busqueda generica
    def siExiste(self, lista, ticker):
        for tt in lista:
            if (tt[0] == ticker): return True
        return False

    ## Busqueda generica que devuelve el elemento buscado si existe
    def buscar(self, lista, ticker):
        for tt in lista:
            if (tt[0] == ticker): return tt
        return None

    ## Imprime el listado de compras hechas
    def printCompras(self):
        print(self.compras)

    ## Agrega la compra a la lista. Persiste la lista en disco.
    def agregarCompra(self, ticker, valor, cantidad, valorVentaMin):
        ahora = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        self.compras.append([
            ticker, valor, cantidad, "000", Estado.ENPROCESO, ahora,
            valorVentaMin
        ])
        self.dao.actualizarCompras(self.compras, self.fecha)

    def larvaBackTest(self, fecha):
        self.logger.info("Ejecutando Backtest.")

        self.logger.debug("Arranca larva: ")

        for campo in self.lista:
            ticker = campo[1]
            print("\t" + ticker)

            fechaS = fecha.strftime('%Y-%m-%d')
            dia = timedelta(days=1)
            fechaE = (fecha + dia).strftime('%Y-%m-%d')
            listaCotizaciones = yf.download(ticker,
                                            start=fechaS,
                                            end=fechaE,
                                            interval='5m')

            for x in range(len(listaCotizaciones)):
                hora = listaCotizaciones.index[x]
                precio = listaCotizaciones.iloc[x]['Close']
                valor_arbi = float(campo[5])
                cotizlocalf = float(precio)
                diferencia = float(valor_arbi) - float(cotizlocalf)
                variacion = float((diferencia) * 100) / float(cotizlocalf)
                if (variacion >= self.DIFPORCENTUALMINCOMPRA):
                    ### Proceso Compra
                    valorCompraMax, valorVentaMin = self.calculoValoresCompraYVenta(
                        ticker, cotizlocalf, valor_arbi)
                    if valorCompraMax != 0 and cotizlocalf != 0 and valorCompraMax >= cotizlocalf and not self.siExiste(
                            self.compras, ticker):
                        #cantidad = self.MONTOCOMPRA // cotizlocalf
                        cantidad = 1
                        print(Fore.GREEN + str(hora) +
                              " AVISO: Comprar: {0:.2f}".format(cantidad) +
                              ", valor: {0:.2f}".format(cotizlocalf) +
                              Fore.RESET)
                        self.compra(ticker, cotizlocalf, cantidad,
                                    valorVentaMin)

                for campo in self.compras:
                    if not self.siExiste(self.ventas, ticker):
                        valorMinVenta = campo[6]
                        if cotizlocalf != 0 and cotizlocalf >= valorMinVenta:
                            self.vender(campo[0], cotizlocalf, campo[2])
                            campo[5] = True