SkillAgentSearch skills...

Friartuck

Live Quant Trading Framework for Robinhood, using IEX Trading and AlphaVantage for Free Prices.

Install / Use

npx skills add codesociety/friartuck

Installs into whichever agent you are using.

README

<!-- [![Image caption](/project.logo.jpg)](#) -->

PROJECT

INSTALL | USAGE | API | [CREDITS][c] | [CONTRIBUTE][cpl] | [LICENSE][cpl] | [SUPPORT][ps]

KISS - Keep it simple, stupid!

Algorithm script file (algo_template.py) ...

import logging
log = logging.getLogger("friar_tuck")
    
def initialize(context, data):
    # (required) is called when the process starts up
    # Note: within this method "initialize", the parameter "data" should primarily be used to load historical data for initialization, the use of data.current(...) method is best within the handle_data(...) method.
    log.info("hello, I am in initialize...")
    
def on_market_open(context, data):
    # (optional) is called when the market opens or after a restart of the process during the live market
    # Note: within this method "on_market_open", the parameter "data" should primarily be used to load historical data for initialization, the use of data.current(...) method is best within the handle_data(...) method.
    log.info("on market open")
    
def handle_data(context, data):
    # (required) is called at each data interval, currently supported frequencies (1m=every minute, 1h=every hour, 1d=every day at end of session).
    log.info("hello, I am in handle_data")

Config file (rh_config.cfg) ...

[LOGIN]
    username = <robinhood username>
    password = <robinhood password>
    
[ALPHA_VANTAGE]
    apikey = <get_your_fee_apikey from www.alphavantage.co>
    wait_for_connection = yes

Run FriarTuck - Live

python friar_tuck_run.py --algo_script algo_template --config_file rh_config.cfg --data_frequency 1h

FRIAR TUCK SUMMARY

Drive for this project: Build an algorithm on Quantopian, was satisfied with the results, the day I was ready to run live I found out that Quantopian was discontinuing live trading... Bummer!!! Quantopian was my only hope for trading algorithmic on Robinhood and thought all hopes were gone. Than I came across the unofficial api for Robinhood (https://github.com/Jamonek/Robinhood), regained some hopes again... Spent sometime leveraging the Jamonek's Python implementation of the API to build a framework similar to Quantopian. Since Quantopian is keeping their framework for backtesting; my aim for this framework is to keep it was close to Quantopian as possible, this way I can backtest on Quantopian and run live using this framework.

Using the following projects/data (Respect!):
    # As a broker to Robinhood
    https://github.com/Jamonek/Robinhood
    
    # IEXTRADING for historical data
    iextrading.com
    # ALPHA VANTAGE for intra-day realtime data (5 requests per minute for free, get your free apikey... more request are offered for premium service)
    www.alphavantage.co
  

GETTING STARTED

REQUIREMENTS

  • ROBINHOOD Trading Account
  • An environment to run FriarTuck (All my testing so far has been on Windows)
  • Python (built this using version 3.4)

INSTALLATION

pip install -r requirements.txt

USAGE

Load Contracts

    context.aapl = lookup_security("AAPL")
    context.wtw = lookup_security("WTW")
    context.fit = lookup_security("FIT")
    ...
    # Get active trading account details
    my_account = context.account
    log.info(my_account)
    ...
    # Get active portfolio details
    my_portfolio = context.portfolio
    log.info(my_portfolio)
    ...
    # Iterate through all open positions
    for security in context.portfolio.positions:
        log.info("symbol(%s) pos(%s) " % (security.symbol, context.portfolio.positions[security]))
    ...

Using "data" object for current data from "handle_data(context, data)"

    # Get current data (all fields [open, high, low, close, volume, price, bid_price, bid_size, ask_price, ask_size])
    current_quote = data.current(context.aapl)
    log.debug(current_quote)
    ...
    # Get current data (specific fields)
    current_quote = data.current(context.aapl, field=['close', 'open'])
    log.debug(current_quote)
    ...
    # Get field(s) for more than 1 security
    current_quote = data.current([context.aapl, context.wtw], field='close')
    log.debug(current_quote)
    

Using "data" object for historical-data from "handle_data(context, data) and on_market_open(context, data)"

    hist_quotes = data.history([context.aapl, context.wtw], frequency='1m', bar_count=10, field='close')
    log.debug(hist_quotes)

    log.debug(context.fit)
    current_data = data.current(context.fit, field=['close', 'price'])
    log.debug(current_data)
    

Sample code using pandas to load contracts from external file

    import pandas as pd
    ...
    context.assets = []
    context.symbol_metadata = {}
    dataset = pd.read_csv("https://dl.dropboxusercontent.com/s/cg8qzffg7yfyzk6/my_universe.csv?dl=0")
    for (index, series) in dataset.iterrows():
        asset = lookup_security(series["symbol"])
        context.symbol_metadata[asset] = series
        context.assets.append(asset)
    log.debug("symbol_metadata (%s)" % context.symbol_metadata)

Ordering using Friar Tuck

    ...
    # Ordering using monetary value; this will use last trade price to calculate number of shares to order
    # for buy
    cash = 1000
    # or for sell
    cash = -1000 
    context.aapl_order_id = order_value(context.aapl, cash, order_type=OrderType(stop_price=158.60), time_in_force='gtc')
        
    ...
    # Ordering a set number of shares
    # for buy
    shares = 120
    # or for sell
    shares = -120
    context.aapl_order_id = order_shares(context.aapl, shares, order_type=OrderType(stop_price=158.60), time_in_force='gtc')
    
    ...
    # retrieve order object
    order = get_order(context.aapl_order_id)
    log.info("order=%s" % order)
    
    ...
    last_filled_buy_order = get_last_filled_buy_order(context.aapl)
    
    ...
    last_filled_sell_order = get_last_filled_sell_order(context.aapl)
    
    ...
    last_filled_orders_by_side = get_last_filled_orders_by_side(context.aapl)
    last_filled_buy_order = last_filled_orders_by_side["buy"]
    last_filled_sell_order = last_filled_orders_by_side["sell"]
    
    ...
    # Retrieve all open orders
    open_orders = get_open_orders()
    for stock_symbol in open_orders:
        log.info("open_order=%s" % open_orders[stock_symbol])
    
    ...
    # Retrieve all open orders by security
    open_orders = get_open_orders(context.aapl.symbol)
    for open_order in open_orders:
        log.info("AAPL open_order=%s" % open_order)
    
    ...
    # Cancel an order
    cancel_order(context.aapl_order_id)

API

WARNING!: This api is subject to change! Make sure you know what you're doing!

Much of this API is the same of similar to Quantopian

Context Object:
    is_market_open (boolean): Indicates if the stock market is open or not.
    account (Account Object): Contains the details about the trading account.
    portfolio (Portfolio Object): holds portfolio details including positions.
    
Security Object: Used when interacting with the broker.
    symbol (string): Stock symbol
    simple_name (string): User-friendly security name
    min_tick_size (float): minimum tick-size of the production, important when supplying a price for an order.
    is_tradeable (boolean): Indicates if the security is tradeable
    security_type (String): The security type
    security_detail (json object): The actual security details from Robinhood
    
OrderType Object: Use to determine the type of order (limit, stop, stop-limit)
    price (float): Use to determine a limit order
    stop_price (float): Use to determine a stop order
    
    Note: both fields can be set from the constructor (price=my_limit_price, stop_price=my_stop_price)... 
    If both fields are obmitted then its a market order, however, 
    please note that though it's a market order to you but robinhood always uses a limit order
    
Order Object: This represents an order on the market
    id (string): this is the unique identifier of the order
    status (integer): The status of the order
        0 = Open (Robinhood confirmed/partially_filled)
        1 = Filled
        2 = Cancelled
        3 = Rejected
        4 = Unconfirmed (Robinhood queued/unconfirmed)
        5 = Failed
    created (datetime): the date and time the order was created
    stop (float): Stop price
    limit (float): Limit price
    amount (int): Shares ordered
    symbol (string): Stock symbol
    filled (boolean): Indicates if the entire order is filled
    commission (float): commissione charged
    rejected_reason (string): if the order was rejected, this will be the reason
    time_in_force (string): (Robinhood [gfd|gtc])
    
Portfolio Object:
    capital_used (float): net capital at play (Total cost of shorts) minus (Total cost of longs)
    cash (float): total cash at hand available for trading (robinhood unsettled cash + cash)
    pnl (float): net profit_loss (equity - uncleared_deposits - equity_previous_close)
    positions (dict): key=Security object, value=Position object
    portfolio_value (float): total value of the portfolio (robinhood unsettled cash + cash + market-value)
    positions_value (float): market_value (Robinhood)
    returns (float): total returns since starting the FriarTuck process ((portfolio_value - starting_cash) / starting_cash)
    starting_cash (float): total available cash at the start of the FriarTuck process
    start_date (datetime): The date and time the FriarTuck process started
    

Related Skills

View on GitHub
GitHub Stars153
CategoryDevelopment
Updated1mo ago
Forks23

Languages

Python

Security Score

100/100

Audited on Jul 3, 2026

No findings