INSTALL | USAGE | API | CREDITS | CONTRIBUTE | LICENSE | SUPPORT
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>
Run FriarTuck - Live
python friar_tuck_run.py --algo_script algo_template --config_file rh_config.cfg --data_frequency 1h
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
# Google's Undocumented Finance API For quotes(ohlcv) (frequencies 1m, 1h, 1d)
finance.google.com/finance/
# Google informatin on delays for quotes(most are realtime)
https://www.google.com/intl/en/googlefinance/disclaimer/
- ROBINHOOD Trading Account
- An environment to run FriarTuck (All my testing so far has been on Windows)
- Python (built this using version 3.4)
pip install -r requirements.txt
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)
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
Position Object: (context->portfolio->positions)
amount (int): The number of shares
cost_basis (float): The average price of the position.
last_sale_price (float): The more recent quote trade price for the security.
created (datetime): create datetime of the position
Account Object: These fields are from Quantopian, I attempt to map them with fields from and calcs from Robinhood
accrued_interest (float): This will always be with Robinhood(could not find a matching field) 0
available_funds (float): cash available for trading (Robinhood unsettled cash + cash)
buying_power (float): value available to buy stock (equity - market_value - cash_held_for_orders)
cushion (float): (Robinhood unsettled cash + cash) / portfolio_value
day_trades_remaining (int): Infinity (could not identify a Robinhood field to match)
equity_with_loan (float): portfolio_value
excess_liquidity (float): (Robinhood unsettled cash + cash)
initial_margin_requirement (float): 0 (could not identify a Robinhood field to match)
leverage (float): current leverage = (long_position_value + short_position_value) / portfolio_value
maintenance_margin_requirement (float): 0 (could not identify a Robinhood field to match)
net_leverage (float): market_value / portfolio_value
net_liquidation (float): portfolio_value
regt_equity (float): (Robinhood unsettled cash + cash)
regt_margin (float): Infinity (could not identify a Robinhood field to match)
settled_cash (float): cash (robinhood cash)
total_positions_value (float): (Robinhood market_value)
You can follow me on twitter.
I want to praise the efforts of the people/projects that have inspired me while
I've been working on this project by briefly mention below their names and projects:
- @Quantopian here
- @Jamonek / Robinhood github.
- Github guides for their precious documenting your project article concerning readme creation
Check out license for more details.
This project is currently in the very alpha phase, its changing all the time; production readiness is fully determined by you. I can not guarantee that this project has no bugs, I do try to minimize them but don't have the time or the resources eliminate them. I am testing this project live as I am using it for my own use, however, I am afraid that my testing is and will be bias since I'll somehow shape it to solve only my problems. To broaden this up, it would be nice to expand this project to solve other quant issues as well. Looking for volunteers to test and to develop this project for others to use. Use of this product is entirely AT YOUR OWN RISK; I do not and can not guarantee any part of this code.
If you want to help me please follow here.
Go back to the project description
Copyright © 2017 Code Society