Trading algorítmico

Como conectar en tiempo real con Coinbase y crear una estrategia de trading RSI

En este tutorial veremos:

  • Como conectar con el API de Coinbase basada en websockets desde Python.
  • Pequeña estrategia basada en RSI (Relative Strength index).

Necesitarás una cuenta en Coinbase si quieres realmente realizar compras o ventas. En este tutorial no será necesario ya que solamente leeremos los datos del API.

Instalación de requisitos previos

instalaremos los siguientes requisitos:

pip install websockets talib 

Fácil ¿no?

Conexión con el API de Coinbase

Ahora vamos a crear nuestra función asíncrona donde leeremos del websocket de Coinbase cuando este disponible un nuevo valor, de ahí la importancia de que sea asíncrona.

Nuestra función quedaría así:

#get data realtime websocket
def get_realtime_data():
    ws = create_connection("wss://ws-feed.pro.coinbase.com")
    ws.send("""{"type": "subscribe","channels": [{ "name": "ticker", "product_ids": ["ETH-EUR"] }]}""")
    res = ws.recv()
    print(res)
    while True:
        res = ws.recv()
        jres = json.loads(res)
        print(jres['price'])
            
await get_realtime_data()

Explicaremos las lineas mas importantes, para empezar necesitamos conectarnos al feed de Coinbase que podemos encontrar en la direccion wss://ws-feed.exchange.coinbase.com:

ws = create_connection("wss://ws-feed.pro.coinbase.com")

una vez conectamos deberemos suscribirnos al canal que nos interese, en nuestro caso nos suscribiremos al canal de ETHEREUM para leer sus valores de cotización, esto lo haremos enviando al socket la siguiente información en formato json:

ws.send("""{"type": "subscribe","channels": [{ "name": "ticker", "product_ids": ["ETH-EUR"] }]}""")
res = ws.recv()

Una vez enviado el mensaje recibiremos una respuesta de que nos hemos suscrito satisfactoriamente, esta información no es relevante y por tanto la obviamos. Si te interesa la respuesta será algo así:

{"type":"subscriptions","channels":[{"name":"ticker","product_ids":["ETH-EUR"]}]}

Posteriormente iniciaremos un bucle infinito en el que leeremos constantemente del websocket (cuando haya información) y la imprimimos por pantalla:

while True:
    res = ws.recv()
    jres = json.loads(res)
    print(jres['price'])

Una vez tengamos conexión y ejecutemos nuestra función mediante get_realtime_data() veremos por pantalla los datos en tiempo real del websocket:

Estrategia de trading

Pues bien ahora toca implementar nuestra estrategia de trading. En primer lugar definiremos nuestro algoritmo en pseudo-codigo:

Mientras Verdad
    Leer datos ws
    Aplicar RSI
    Si RSI es menor de 30
        Compramos
        Mientras Verdad
            Si Precio actual es mayor que el precio de compra + 0.1%
                vendemos
                rompemos bucle
            Si el precio actual es menor que stop loss (precio de compra - 5%)
                vendemos
                rompemos bucle

Esto traducido al lenguaje Python quedaría así:

 
    historic_data = pd.DataFrame(columns=['close'])
    while True:
        res = ws.recv()
        jres = json.loads(res)
        #print(jres['price'])
        historic_data = historic_data.append({'close':Decimal(jres['price'])}, ignore_index=True)
        rsi = talib.RSI(historic_data['close'])
        if(len(rsi)<20):
            print("Historico acumulado: {} elementos".format(len(rsi)))
        if(len(rsi)>20):
            #conditions to buy
            if (rsi.values[-1]<=30):
                last_entry = historic_data['close'].values[-1]
                print("Buy at: {}".format(last_entry))
                print("Target at: {}".format(last_entry*Decimal(1.001)))
                print("Loss at: {}".format(last_entry-(last_entry*Decimal(0.05))))
                print("Actual RSI: {}".format(rsi.values[-1]))
                while True:
                    #conditions to sell
                    res = ws.recv()
                    jres = json.loads(res)
                    #print(jres['price'])
                    historic_data = historic_data.append({'close':Decimal(jres['price'])}, ignore_index=True)
                    rsi = talib.RSI(historic_data['close'])

                    #if ((last_entry*Decimal(1.001)) <= Decimal(jres['price'])):
                    if ((last_entry*Decimal(1.001)) <= Decimal(jres['price'])):
                        print("Sell to price {}".format(jres['price']))
                        print("RSI was {}".format(rsi.values[-1]))
                        break
                    if (last_entry-(last_entry*Decimal(0.05))) > Decimal(jres['price']):
                        print("Sell to stop loss with price {}".format(jres['price']))
                        break

En historic_data crearemos un dataFrame en el que guardaremos el histórico con el que calcularemos el indicador RSI, tendremos que acumular una serie de valores histórico para poder hacerlo en nuestro caso nos quedaremos con 20 valores antes de empezar a calcularlo.

una vez hecho aplicamos la lógica en pseudo-código. Vamos a ejecutar nuestro algoritmo (en ningún caso se compra o se vende, en esta versión simplemente mostramos un msg por pantalla para hacer un debug de lo que se está haciendo. La salida por consola seria algo así:

Historico acumulado: 1 elementos
Historico acumulado: 2 elementos
Historico acumulado: 3 elementos
Historico acumulado: 4 elementos
Historico acumulado: 5 elementos
Historico acumulado: 6 elementos
Historico acumulado: 7 elementos
Historico acumulado: 8 elementos
Historico acumulado: 9 elementos
Historico acumulado: 10 elementos
Historico acumulado: 11 elementos
Historico acumulado: 12 elementos
Historico acumulado: 13 elementos
Historico acumulado: 14 elementos
Historico acumulado: 15 elementos
Historico acumulado: 16 elementos
Historico acumulado: 17 elementos
Historico acumulado: 18 elementos
Historico acumulado: 19 elementos
Buy at: 3332.08
Target at: 3335.412079999999633024287959
Loss at: 3165.475999999999990751620160
Actual RSI: 27.14705938726517
Sell to price 3335.72
RSI was 70.5475192624942
Buy at: 3332.07
Target at: 3335.402069999999633025389301
Loss at: 3165.466499999999990751647916
Actual RSI: 28.157293437328697
Sell to price 3335.51
RSI was 67.22625240354468
Buy at: 3334.47
Target at: 3337.804469999999632761067403
Loss at: 3167.746499999999990744986578
Actual RSI: 29.103058112202024

Como se puede observar una vez acumulados 20 elementos (el mensaje es mejorable) comienza el «trading» al tener el indicador RSI, en el tiempo de ejecución del script realiza una compra de 3332.08 y una venta de 3335.72, vuelve a comprar a 3332.07 y vende a 3335.51 y por último compra a 3334.47 y se queda a la espera de una nueva subida de un 0.1% o una bajada del 5% en ambos casos venderíamos.

Lo normal si usamos una estrategia RSI es que siempre compremos cuando el RSI está en valores por debajo de 30 y vendamos cuando el valor alcance 70. En este tutorial la estrategia usada esta enfocada mas a fines didácticos por lo que el limite o el rango de compra venta es mas bajo para fomentar las entradas y salidas.

Espero que os haya gustado, podéis consultar mi canal en Youtube para ver en tiempo real como desarrollar esta estrategia.

P.D: No soy ningún experto, os recomiendo que hagáis vuestro propio análisis y recordad que el trading sobre todo con criptomonedas conlleva un gran riesgo 🙂

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *