top of page

Controlador Retroalimentado Robusto con Bitcoin

El precio de las criptomonedas ha despegado como un cohete lanzado a la luna contra los dólares y euros. Esta tendencia ha atraído la atención de los medios causando un bucle de interés retroalimentado: a más precio, más atención, más participantes con miedo a quedarse fuera, más aumento de precio. Es posible que en un futuro las criptomonedas sean capaces de ofrecer el mismo servicio que dan las monedas fiduciarias actualmente: medio de intercambio y almacén de valor, principalmente. Para dar este servicio correctamente, o al menos para permitir una transición ordenada a estas funciones, se necesita una cierta estabilidad del cambio contra otros activos (sobre todo los rotantes). El valor de cambio ha variado mucho últimamente en lo que podría entenderse ya como una forma de cambio de moneda extranjera, esta vez hacia arriba, ganando valor relativo contra los fiduciarios comunes. Como si el “país Bitcoin” hubiese aumentado doblado su producto interior bruto. Todo crítico de las criptomonedas espera una aguda caída que le demuestre al mundo que la moneda criptográfica todavía no esta lista para su función, no sirve como tal. Sin criticar mas las criptomonedas, sí, es ciertp, la posibilidad de sufrir grandes perdidas de valor está ahí, es prácticamente una certeza matemática. Veamos lo que ha ocurrido en los pasados meses para el precio de cambio BTC-USD para ilustrar la parte bonita de la situación:

Y el volumen relativo, desde una única casa de cambio. Encontrar el valor real de volumen intercambiado para las criptomonedas es difícil, por ahora los valores relativos tendrán que bastar para hacernos una idea de con cuanto se comercia:


En este periodo, la desviación estándar de los retornos diarios es del 4,25%. Una volatilidad media mensual del 22% o una volatilidad anualizada del 80%, tomando solamente este periodo en consideración. Si tomásemos cualquier otro periodo de un año para nuestro análisis el resultado no variaría mucho tampoco, en efecto, Bitcoin medido en USD es altamente volátil y el 80% del valor se puede esfumar en un año, o su valor se puede doblar en unos pocos meses. Es una situación de riesgo y beneficio extremos.


Invertir es un acto de equilibrio casi acrobático entre el riesgo y el beneficio y sin duda existen individuos e instituciones con un apetito para el riesgo elevado a los que les gustaría asumir un poco más de riesgo a cambio de capturar los beneficios que las criptomonedas puedan traer en el futuro. Esta no es una postura temeraria en sí misma si adoptamos un proceso cuantitativo a la hora de invertir en, o especular con, Bitcoin y mantenemos una exposición alta o baja según nuestras preferencias de riesgo. El riesgo se tiene que reconocer, analizar y luego se tomaran las posiciones de inversión necesarias con consciencia de los múltiples resultados posibles.


Una vez hemos decidido que queremos arriesgar hasta el 80% del valor de nuestra inversión cada año a cambio de unas ganancias potenciales similares podemos implementar métodos de control adicionales que minimicen este riesgo y maximicen los beneficios. Uno de estos métodos es un sistema de control lineal tal como el que se describe en este articulo: On Trading of Equities: A Robust Control Paradigm. Aquí se presenta por primera vez (que sepamos) un sistema simple de control lineal retroalimentado que modula nuestra inversión en cualquier activo dependiendo de los retornos de los periodos anteriores multiplicados por un cierto valor de ganancia. El propio articulo contiene la imagen de la arquitectura de semejante controlador, que es relativamente simple:


El modelo del código que refleja esta estrategia de control y nos ayuda a modular la exposición a activos de riesgo comienza con las importaciones de necesarias y la inicialización general de un algoritmo bajo el marco de desarrollo de Quantconnect:

import numpy as np
import pandas as pd
class CryptoController(QCAlgorithm):

    def Initialize(self):

        self.SetStartDate(2020, 12, 1)
        self.SetEndDate(datetime.today())
        self.SetCash(1000000)
        self.SetBrokerageModel(BrokerageName.Bitfinex, AccountType.Margin)

        res = Resolution.Hour
        self.SetPortfolioConstruction(InsightWeightingPortfolioConstructionModel())
        self.Settings.RebalancePortfolioOnInsightChanges = Trueself.SetExecution(ImmediateExecutionModel())
        self.UniverseSettings.Resolution = res

        # Instrumento para comerciar.
        crypto = ['BTCUSD']

        # Parametro Ganancia K, 4 como en la referencia:
        try:
            self.K = float(self.GetParameter("K"))
        except:
            self.Debug('No K-gain parameter detected. Using default')
            self.K = float(4)

        # Creacion de simbolos:
        self.crypto = [self.AddCrypto(ticker, res).Symbol for ticker in crypto]
        self.AddAlpha(CryptoControl(self.crypto, self.K))

Asignamos un valor de ganancia “K” de 4 de acuerdo con el artículo original. El último cambio en el precio en resolución horaria (nuestro Resolution.Hour) se multiplicará por 4 (“K) para obtener los cambios en el porcentaje de exposición. El modelo permite un ajuste flexible de K para que podamos comprobar su comportamiento para diferentes valores. Las investigaciones posteriores realizadas en este campo se concentran en una definición más formal de la función de ganancia. Un controlador hipotético podría usar alguna métrica de volatilidad como ganancia, no hemos encontrado ninguna publicación al respecto.


El modelo invertirá un porcentaje del total de nuestros activos en el par BTCUSD, el resto se mantendrá en USD por simplicidad, pero se podría asignar a cualquier inversión de bajo riesgo. La casa de cambio que utilizamos en este modelo es Bitfinex, ya que la implementación de las interfaces en Quantconnect permite el uso de cuentas de margen y simplifica el desarrollo de este algoritmo de prueba. Honestamente no tenemos ninguna preferencia respecto a la casa de cambio, si mencionamos un intermediario especifico es se deben siempre a razones técnicas relacionadas con la disponibilidad de una API y sus interfaces. Para una evaluación de diferentes casas de cambio www.commodity.com contiene información sobre múltiples alternativas, también contiene información interesante sobre comercio de materias primas en general.


Tenemos que iniciar el modelo AlphaModel para definir las condiciones iniciales y las estructuras de datos a almacenar en forma de diccionarios de Python:

class CryptoControl(AlphaModel):
    def __init__(self,
                 crypto,
                 K):
        self.Name = 'Crypto Controller'self.crypto = crypto
        self.K = K
        self.total_assets = len(self.crypto)
        self.init = False# Dictionaries for data:self.changes = {}
        self.loads = {}
        self.gains = {}
        
        # Filtro de paso bajo para pesos muy pequeños, las posiciones por debajo de epsilon (0.005%) se asignan en 0 para evitar señales que resultarian en ninguna operacion.
        self.epsilon = 0.005
        # Submuestreo del cliclo en raiz cuadrada.
        self.subsampler = int(np.sqrt(int(self.K)))
        self.sample = 0

Actuaremos contra los datos a la misma velocidad a la que los recibimos si no submuestreamos las señales de compra y venta. Emitimos un nuevo objetivo de cartera cada parte entera de la raíz cuadrada de la ganancia (2 en este caso) para sincronizar la generación de dos señales consecutivas. Añadimos también un límite mínimo de movimiento, los pesos de menos de 0,005% se considerarán 0 para evitar emitir ordenes imposiblemente pequeñas.


El método Update del modelo alfa, el método que se ejecutará cuando se reciba una rodaja de datos, contiene el siguiente código, donde computamos la ganancia y se generan las señales de carga de cartera:

 # Compute the gain g for crypto symbols:
 for symbol in self.crypto:
            self.gains[symbol] = self.changes[symbol].Current.Value*self.K
            self.loads[symbol] = min(max(self.loads[symbol] + self.gains[symbol], 0), 1)
        
        # Subsample to avoid sync with rebalance and insight periods.
        if self.sample % self.subsampler != 0: return[]
        
        # Obtain insight time delta and magnitudes.
        t_delta = timedelta(hours=self.subsampler)
        magnitude_values = np.array(list(self.gains.values()))
        magnitude = abs(np.mean(magnitude_values))*100
        for symbol in self.crypto:
            w = self.loads[symbol] 
            g = self.gains[symbol]
            if w <= self.epsilon: continue
            if abs(g) <= self.epsilon/10000: continue
            
            insights.append(Insight(symbol, t_delta,
                                    InsightType.Price,
                                    InsightDirection.Up,
                                    magnitude, int(True),
                                    self.Name, w))
                                    

        return insights

The rest of the details on the initialization and error management are in the sample back-test at the end of the publication.


En términos de resultados, primero miraremos al destino de nuestra inversión si hubiésemos invertido el 100% de nuestro capital (1 millón de USD, soñar es gratis) en Bitcoin hace 60 días para mantenerlo con un modelo simple, hipotético y totalmente condicional:


No es en absoluto un mal resultado ya que capturamos el cohete de Bitcoin. Comprobaremos ahora el mismo periodo utilizando nuestro controlador de ganancia para modular la inversión dependiendo de los retornos pasados. Esto es básicamente un modelo técnico de circuito cerrado que nos dice si añadir o sustraer de la posición con un factor K (4 en este caso):


Comparando el modelo controlado contra el simple observamos dos valores destacados: los beneficios son un 15% menos en el modelo controlado y además las comisiones de compraventa son astronómicamente altas. Aparentemente el modelo no ha hecho nada bueno… Una mirada más detallada a los retornos y la volatilidad muestra una diferencia en el ratio de Sharpe probabilístico del modelo del 4%, que no parece bueno en ninguno de los dos modelos hasta que miramos a las perdidas máximas. Para el modelo simple la perdida máxima es del 30%, para el modelo controlado es de “solamente” el 19% (la altísima volatilidad entra en juego). Pagamos en retornos y en comisiones por una cierta paz mental. En vez de terminar con 1,65M terminamos con 1,5M y unas mañanas de domingo un 11% menos alarmantes. Los mercados de criptomonedas no paran. No paran de hacer sufrir.


Lo que el controlador está haciendo es mejorar levemente la relación entre riesgo y beneficio para cualquier forma de señal temporal. Persigue el momento en alta frecuencia. El modelo no podrá transformar un mercado descendente o un activo en caída en una inversión rentable, lo máximo que podrá hacer será limitar las pérdidas. De la misma manera limitara las ganancias y alterara los perfiles de ganancias y pérdidas máximas a una combinación menos volátil de ambas.


El peor periodo para Bitcoin (y para las criptomonedas en general) fue desde enero de 2018 hasta agosto de 2018. En este periodo el tamaño del desastre para el modelo de comprar y mantener fue de unas pérdidas del 43%:


En este mismo periodo, bajo control, perdemos un 30%; una diferencia notable en valor al final del periodo a nuestro favor:


Las criptomonedas son activos de riesgo, matemáticamente hablando, y en términos de volatilidad de los retornos. Cualquier intento de participar en sus futuros beneficios tiene que estar perfectamente calibrado en cuanto a riesgo y beneficio. La volatilidad se debe seguir estudiando constantemente y según las criptomonedas vayan demostrando o no su razón de ser. La situación puede cambiar lentamente hasta que la volatilidad desaparezca y las criptomonedas se estabilicen como medio de pago, si es que esto llega a ocurrir. El mercado no presenta síntomas de relajación así que se mantiene como una apuesta arriesgada con un precio fundamental muy difícil de descubrir. Sinceramente, no creemos que semejante precio fundamental se pueda predecir con precisión alguna ni para Bitcoin ni para otras monedas o tokens de aplicación. Lo mejor que podemos hacer es mitigar los riesgos para obtener unas rentabilidades aceptables sea cual sea la dirección del mercado de criptomonedas. Cada inversor debe mantener una posición cómoda para su apetito de riesgo y tolerancia a las perdidas.


ILas publicaciones en Ostirion.net no son consejos financieros ni forman parte de un servicio de asesoramiento financiero. Ostirion.net no mantiene posiciones en ninguno de los instrumentos financieros que se mencionan en esta publicación en el momento de la publicación. Si necesita más información, apoyo con la gestión de activos financieros, desarrollo de estrategias de trading automatizados o despliegue táctico de estrategias existentes no dude en contactar con nosotros aquí. El modelo de esta publicacion se puede clonar desde aquí:


33 views0 comments
bottom of page