The goal of this story is to create the simplest paper trading bot in Alpaca which will use WebSocket 1-minute bars. The strategy is
Buy 0.1 BTC at Market if RSI_14 < 30 and HAVE_NO_POSITIONSell 0.1 BTC at Market if RSI_14 > 70 and HAVE_POSITION
YouTube Video
https://medium.com/media/61d42518884e876d57f7a501b30f2eaf/href
Installations
Install alpaca-py!pip install aplaca-py
2. Install pandas_ta
!pip install pandas_ta
API Keys + Secrets
from google.colab import userdata
ALPACA_API_KEY=userdata.get(‘ALPACA_API_KEY’)
ALPACA_API_SECRET=userdata.get(‘ALPACA_API_SECRET’)
Nest Asyncio
Allow nested use of asyncio within Jupyter notebooks, Google Colab, or other environments that already have an event loop running.Written by the legend Ewald De Wit RIPimport nest_asyncio
nest_asyncio.apply()
Initialize Paper Trading Client
from alpaca.trading.client import TradingClient
trading_client = TradingClient(ALPACA_API_KEY, ALPACA_API_SECRET, paper=True)
Crypto Data Stream for Websocket Data
Initialize CryptoDataStream
Used to manage real-time Crypto Websocket data.from alpaca.data.live import CryptoDataStream
crypto_data_stream = CryptoDataStream(ALPACA_API_KEY, ALPACA_API_SECRET)
Define Event Handler when New Bar Arrives
This is where we put our trading logicAnalogous to callback in ib_insyncfrom alpaca.trading.requests import MarketOrderRequest
from alpaca.trading.enums import OrderSide, TimeInForce
from pandas_ta.momentum import rsi
bars = []
has_position = False
async def on_new_bar(bar):
global bars
global has_position
bars.append(bar)
if len(bars)<15:
print(“Not Enough Data”)
else:
rsi_value = rsi(util.df(bars[-15:]).close).iloc[-1]
print(f”Current RSI is {rsi_value}”)
if has_position and rsi_value>=70:
print(“RSI is overbought, sell BTC”)
trading_client.submit_order(
order_data=MarketOrderRequest(
symbol=”BTC/USD”,
qty=.1,
side=OrderSide.SELL,
time_in_force=TimeInForce.GTC
)
)
has_position = False
elif not has_position and rsi_value<=30:
print(“RSI is oversold, buy BTC”)
trading_client.submit_order(
order_data=MarketOrderRequest(
symbol=”BTC/USD”,
qty=.1,
side=OrderSide.BUY,
time_in_force=TimeInForce.GTC
)
)
has_position = TrueNote we used the following helper function util.df to convert a list of bars into a Pandas DataFrameimport pandas as pd
class util:
@staticmethod
def df(json_like):
if isinstance(json_like, list):
json_like = [element.__dict__ for element in json_like]
return pd.DataFrame(json_like)
else:
json_like = json_like.__dict__
return pd.DataFrame(json_like.values(), index=json_like.keys())
Subscribe to Websocket 1-minute Bars and attach Event Handler
crypto_data_stream.subscribe_bars(on_new_bar, “BTC/USD”)
Run the Algo (BLOCKING)
crypto_data_stream.run()
Run the Algo (NON BLOCKING)
import asyncio
asyncio.create_task(crypto_data_stream._run_forever())If you are using Jupyter/Colab and still want it to be Interactive this is useful
Sample Output:
Crypto Trading Bot in Alpaca was originally published in Coinmonks on Medium, where people are continuing the conversation by highlighting and responding to this story.