Trading





Kerry Back

Steps

  • Generate current predictions as in the previous session to obtain a dataframe indexed by ticker with a “predict” column.
  • Add information from Alpaca
    • tradable and shortable status
    • bid and ask prices
    • current positions

  • For longs, choose the best tradable stocks.
  • For shorts, choose the worst shortable stocks.
  • To equal weight, set target weights = multiple/numstocks.
  • To compute trades:
    • target $ value = equity * target weight
    • target shares = target $ value / price
    • trade = target shares - current shares

Example

  • 150/50
  • Longs = 100 best tradable stocks equally weighted
  • Shorts = 100 worst shortable stocks equally weighted
  • Target dollars:
    • Longs = 0.015 * equity
    • Shorts = 0.005 * equity
  • Trades = (target dollars - current dollars) / ask or bid

Tradable and shortable

from alpaca.trading.client import TradingClient

trading_client = TradingClient(KEY, SECRET_KEY, paper=True)
assets = trading_client.get_all_assets()

df["tradable"] = {
  x.symbol: x.tradable for x in assets
}

df["shortable"] = {
  x.symbol: x.shortable for x in assets
}

Bid and ask prices

from alpaca.data import StockHistoricalDataClient
from alpaca.data.requests import StockLatestQuoteRequest

data_client = StockHistoricalDataClient(KEY, SECRET_KEY)
params = StockLatestQuoteRequest(
  symbol_or_symbols=df.index.to_list()
)
quotes = data_client.get_stock_latest_quote(params)

df["ask"] = {x: quotes[x].ask_price for x in quotes}
df["bid"] = {x: quotes[x].bid_price for x in quotes}

Account equity and current positions

account = trading_client.get_account()
equity = float(account.equity)

current = trading_client.get_all_positions()
df["current"] = (
    {x.symbol: int(x.qty) for x in current} 
    if len(current)>0 else 0
)
df["current"] = df.current.fillna(0)

Ranking tradable and shortable stocks

df["predict"] = np.where(
  df.tradable & (df.ask>0), 
  df.predict, np.nan
)
df["rank_from_top"] = df.predict.rank(
  ascending=False, 
  method="first"
)

df["predict"] = np.where(
  df.shortable & (df.bid>0), 
  df.predict, np.nan
)
df["rank_from_bottom"] = df.predict.rank(method="first")

Longs and shorts

numlong = numshort = 100

df["long"] = df.rank_from_top <= numlong
df["short"] = df.rank_from_bottom <= numshort

print(f"number long is {len(df.long)}")
print(f"number short is {len(df.short)}")

Targets and trades

df["target_dollars"] = (
  (1.5*equity/numlong)*df.long - 
      (0.5*equity/numshort)*df.short
)
df["current_dollars"] = df.current*(df.bid+df.ask)/2
df["trade_dollars"] = df.target_dollars - df.current_dollars
df["trade"] = (
    (df.trade_dollars>0)*df.trade_dollars/df.ask
    + (df.trade_dollars<0)*df.trade_dollars/df.bid
)
df["trade"] = df.trade.fillna(0)
df["trade"] = df.trade.astype(int)

Submit trades

from alpaca.trading.requests import MarketOrderRequest
from alpaca.trading.enums import OrderSide, TimeInForce

for tick in df[df.trade!=0].index:
  market_order_data = MarketOrderRequest(
    symbol=tick,
    qty=abs(df.trade[tick]),
    side=OrderSide.BUY if df.trade>0 else OrderSide.SELL,
    time_in_force=TimeInForce.DAY
  )
  market_order = trading_client.submit_order(
    order_data=market_order_data
  )

Save data

  • trades, new positions, and account equity
  • See 4f notebook in binder for an example.