Criando robôs para compra e venda de criptomoedas

 

Belo Horizonte, 2019

RODRIGO BRITO

- Mineiro | Atleticano

- Desenvolvedor | Gopher

- Pesquisador | DCC/UFMG

www.brito.com.br

Antes de começar...

Esta palestra

não é sobre pirâmides

Esta palestra não é sobre tranformar R$1.5K em R$1M

Esta é uma palestra sobre tecnologia e desenvolvimento

TLDR;

Primeiros passos para criar o seu primeiro robô de finanças

COMO FUNCIONA?

Exchange

Uma criptomoeda não vale nada...

...até que alguém pague algo por ela!

OFERTA E DEMANDA

Mercado de Criptomoedas

  • 24 horas / 7 dias por semana
  • Altamente volátil
  • Alta liquidez
  • Exige respostas rápidas
 

Poxa Rodrigo, mas eu não sou um robô...

BÁSICO

COMPRA

VENDE

BULL MARKET

BEAR MARKET

INDICADORES

RSI - Relative Strength Index

COMPRA

VENDE

Moving Average (SMA, EMA, TEMA)

COMPRA

VENDE

Filtros - Moving Average

Alerta - URSO

BOLLINGER BANDS

RSI

MACD

NVT

EMA

ADX

DMI

ROC

RVI

STOCH RSI

BACKTRADER

BACKTRADER

  • Open Source
  • Python 2 / 3
  • Dezenas de indicadores disponíveis
  • Criação de gráficos
  • Backtesting (Dados históricos)
  • Extensível

$ pip install backtrader

Básico em Desenvolvimento

# Iniciando backtrader
cerebro = bt.Cerebro(quicknotify=True)

# Incluindo dataset
data = GenericCSVData(name="USDT", dataname="dataset/binance.csv")
cerebro.resampledata(data, timeframe=bt.TimeFrame.Minutes, compression=30)
# or cerebro.adddata(data)

# Simulando caixa
broker = cerebro.getbroker()
broker.setcommission(commission=0.001, name="BTC")
broker.setcash(100000.0)

# Incluindo estratégia
cerebro.addstrategy(MyFirstStrategy) # 90% da mágica acontece aqui

# Executando
cerebro.run()
cerebro.plot()

Broker em Produção

broker_config = {
    'apiKey': '<BINANCE KEY>',
    'secret': '<BINANCE SECRETE>',
    'nonce': lambda: str(int(time.time() * 1000)),
    'enableRateLimit': True,
}

store = CCXTStore(exchange='binance', currency="USDT", config=broker_config, retries=5)

broker_mapping = {
    'order_types': {
        bt.Order.Market: 'market',
        bt.Order.Limit: 'limit',
        bt.Order.Stop: 'stop-loss',
        bt.Order.StopLimit: 'stop limit'
    },
    'mappings': {
        'closed_order': {
            'key': 'status',
            'value': 'closed'
        },
        'canceled_order': {
            'key': 'status',
            'value': 'canceled'
        }
    }
}

broker = store.getbroker(broker_mapping=broker_mapping)
cerebro.setbroker(broker)

Estratégia

Estrutura Básica

import backtrader as bt


class MyFirstStrategy(bt.Strategy):

    def __init__(self):
        self.dataclose = self.datas[0].close
        self.rsi = bt.indicators.RelativeStrengthIndex(period=14)
        
    # Executado a cada novo "candle"
    def next(self):
        print('Price: %.2f' % self.dataclose[0])

Parâmetros

class MyStrategy(bt.Strategy):
    params = dict(period_sma_fast=10, period_sma_slow=200)

    def __init__(self):
        sma_fast = bt.indicators.SimpleMovingAverage()
        sma_slow = bt.indicators.SMA(self.datas[0], period=self.p.period_sma_slow)

self.p e self.params

cerebro.addstrategy(MyFirstStrategy, period_sma_fast=25)

Uso na definição de estratégia

Data Feed

def next(self):
    # Aliases
    print(self.data.close)
    print(self.datas[0].close)
    print(self.data0.close)

    # Dados anteriores (últimos 10 candles)
    print(self.data.close.get(size=10))

    # Compara atual e último candle
    print(self.data.close[0] > self.data.close[-1])

    # Comparações entre linhas
    print(self.data.close > sma)
    print(sma > 30)

Operações

# Compra/Venda com preço de mercado (Market Order)
order = self.buy()
order = self.sell()

# Compra com validade
order = self.buy(valid=datetime.datetime.now() + datetime.timedelta(days=3))

# Compra com preço customizado
order = self.buy(price=self.data.close[0] * 0.95)

# Compra com quantidade customizada
order = self.buy(size=25)

# Compra limitada (Limit Order)
order = self.buy(exectype=Order.Limit,
                 price=self.data.close[0] * 0.95,
                 valid=datetime.datetime.now() + datetime.timedelta(days=3)))


# Cancelar ordem
self.broker.cancel(order)

Buy, Sell, Cancel

Controle - Ordens

def notify_order(self, order):
        print('An order new/changed/executed/cancelled has been received')
def notify_order(self, order):
    if order.status in [order.Submitted, order.Accepted]:
        self.log('ORDER ACCEPTED/SUBMITTED', dt=order.created.dt)
        self.order = order # Importante controlar as operações.
        return

    if order.status in [order.Expired]:
        self.log('BUY EXPIRED')

    elif order.status == order.Completed:
        if order.isbuy():
            self.log('BUY EXECUTED, Price: %.2f' % order.executed.price)
        else:
            self.log('SELL EXECUTED, Price: %.2f' % order.executed.price)

Exemplo

Controle - Posição

# Posicionamento no mercado
position = self.position
position = broker.getposition()

if position:
    # Tenho criptomoedas em carteira
def notify_order(self, order):
    elif order.status == order.Completed:
        if order.isbuy():
            self.last_operation = "BUY"
        else:
            self.last_operation = "SELL"

Controle manual (Workaround de precisão)

Hora do show!

Live Code

DATASET

BTC / USDT - Nov - Mar (4 Meses)

Link para Download

Bear Market -44%

Estratégia 1: RSI

def init(self):
    self.rsi = bt.indicators.RelativeStrengthIndex()

def next(self):
    if self.rsi < 30:
        self.buy()
    
    if self.rsi > 70:
        self.sell()

RESULTADO

PREJUÍZO -15.578%

51 Trades / 24 Won / 27 Lost

Estratégia 2: RSI+EMA

def init(self):
    self.rsi = bt.indicators.RelativeStrengthIndex()
    self.ema_fast = bt.indicators.EMA(period=20)
    self.ema_slow = bt.indicators.EMA(period=200)


def next(self):
    if self.rsi < 30 and self.ema_fast > self.ema_slow:
        self.buy()

    if self.rsi > 70:
        self.sell()

Resultado

LUCRO 19.193%

10 Trades / 7 Won / 3 Lost

@RodrigoFBrito

github.com/rodrigo-brito

brito.com.br

Made with Slides.com