python-pour-finance/10-Plateforme-Quantopian/.ipynb_checkpoints/02-Basic-Algorithm-Methods-...

374 lines
14 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Basic Algorithm Methods\n",
"\n",
"Let's algorithmically test our earlier optimized tech portfolio strategy with Quantopian!\n",
"\n",
"#### THIS CODE ONLY WORKS ON QUANTOPIAN. EACH CELL CORRESPONDS WITH A PART OF THE VIDEO LECTURE. MAKE SURE TO WATCH THE VIDEOS FOR CLARITY ON THIS!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**initialize()**\n",
"\n",
"initialize() is called exactly once when our algorithm starts and requires context as input.\n",
"\n",
"context is an augmented Python dictionary used for maintaining state during our backtest or live trading, and can be referenced in different parts of our algorithm. context should be used instead of global variables in the algorithm. Properties can be accessed using dot notation (context.some_property)."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"** handle_data() **\n",
"\n",
"handle_data() is called once at the end of each minute and requires context and data as input. context is a reference to the same dictionary in initialize() and data is an object that stores several API functions."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Our Tech Stock Optimized Portfolio\n",
"\n",
"Let's use the tech stock portfolio we calculated earlier. Keep in mind that handle_data() is readjusting our portfolio every minute! That may be unreasonable for certain algorithms, but for this example, we will just continue with these basics functions."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"def initialize(context):\n",
" # Reference to Tech Stocks\n",
" context.aapl = sid(24)\n",
" context.csco = sid(1900)\n",
" context.amzn = sid(16841)\n",
"\n",
"def handle_data(context, data):\n",
" # Position our portfolio optimization!\n",
" order_target_percent(context.aapl, .27)\n",
" order_target_percent(context.csco, .20)\n",
" order_target_percent(context.amzn, .53)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Grabbing Current Data"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### data.current()\n",
"data.current() can be used to retrieve the most recent value of a given field(s) for a given asset(s). data.current() requires two arguments: the asset or list of assets, and the field or list of fields being queried. Possible fields include 'price', 'open', 'high', 'low', 'close', and 'volume'. The output type will depend on the input types"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"def initialize(context):\n",
" # Reference to Tech Stocks\n",
" context.techies = [sid(16841),sid(24),sid(1900)]\n",
"\n",
"def handle_data(context, data):\n",
" # Position our portfolio optimization!\n",
" tech_close = data.current(context.techies,'close')\n",
" print(type(tech_close)) # Pandas Series\n",
" print(tech_close) # Closing Prices "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"##### Note! You can use data.is_stale(sid(#)) to check if the results of data.current() where generated at the current bar (the timeframe) or were forward filled from a previous time."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Checking for trading"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### data.can_trade()\n",
"\n",
"data.can_trade() is used to determine if an asset(s) is currently listed on a supported exchange and can be ordered. If data.can_trade() returns True for a particular asset in a given minute bar, we are able to place an order for that asset in that minute. This is an important guard to have in our algorithm if we hand-pick the securities that we want to trade. It requires a single argument: an asset or a list of assets."
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"def initialize(context):\n",
" # Reference to amazn\n",
" context.amzn = sid(16841)\n",
" \n",
"def handle_data(context, data):\n",
" # This insures we don't hit an exception!\n",
" if data.can_trade(sid(16841)):\n",
" order_target_percent(context.amzn, 1.0)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Checking Historical Data\n",
"\n",
"When your algorithm calls data.history on equities, the returned data is adjusted for splits, mergers, and dividends as of the current simulation date. In other words, when your algorithm asks for a historical window of prices, and there is a split in the middle of that window, the first part of that window will be adjusted for the split. This adustment is done so that your algorithm can do meaningful calculations using the values in the window.\n",
"\n",
"This code queries the last 20 days of price history for a static set of securities. Specifically, this returns the closing daily price for the last 20 days, including the current price for the current day. Equity prices are split- and dividend-adjusted as of the current date in the simulation:"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"\n",
"def initialize(context):\n",
" # AAPL, MSFT, and SPY\n",
" context.assets = [sid(24), sid(1900), sid(16841)]\n",
"\n",
"def before_trading_start(context,data):\n",
" price_history = data.history(context.assets,fields=\"price\", bar_count=5, frequency=\"1d\")\n",
" \n",
" print(price_history)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The bar_count field specifies the number of days or minutes to include in the pandas DataFrame returned by the history function. This parameter accepts only integer values.\n",
"\n",
"The frequency field specifies how often the data is sampled: daily or minutely. Acceptable inputs are 1d or 1m. For other frequencies, use the pandas resample function."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Examples\n",
"Below are examples of code along with explanations of the data returned.\n",
"\n",
"### Daily History\n",
"\n",
"Use \"1d\" for the frequency. The dataframe returned is always in daily bars. The bars never span more than one trading day. For US equities, a daily bar captures the trade activity during market hours (usually 9:30am-4:00pm ET). For US futures, a daily bar captures the trade activity from 6pm-6pm ET (24 hours). For example, the Monday daily bar captures trade activity from 6pm the day before (Sunday) to 6pm on the Monday. Tuesday's daily bar will run from 6pm Monday to 6pm Tuesday, etc. For either asset class, the last bar, if partial, is built using the minutes of the current day.\n",
"\n",
"### Examples (assuming context.assets exists):\n",
"\n",
"* data.history(context.assets, \"price\", 1, \"1d\") returns the current price.\n",
"* data.history(context.assets, \"volume\", 1, \"1d\") returns the volume since the current day's open, even if it is partial.\n",
"* data.history(context.assets, \"price\", 2, \"1d\") returns yesterday's close price and the current price.\n",
"* data.history(context.assets, \"price\", 6, \"1d\") returns the prices for the previous 5 days and the current price.\n",
"\n",
"\n",
"### Minute History\n",
"\n",
"Use \"1m\" for the frequency.\n",
"\n",
"Examples (assuming context.assets exists):\n",
"\n",
"* data.history(context.assets, \"price\", 1, \"1m\") returns the current price.\n",
"* data.history(context.assets, \"price\", 2, \"1m\") returns the previous minute's close price and the current price.\n",
"* data.history(context.assets, \"volume\", 60, \"1m\") returns the volume for the previous 60 minutes."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Scheduling\n",
"\n",
"Use schedule_function to indicate when you want other functions to occur. The functions passed in must take context and data as parameters."
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"def initialize(context):\n",
" context.appl = sid(49051)\n",
"\n",
" # At ebginning of trading week\n",
" # At Market Open, set 10% of portfolio to be apple\n",
" schedule_function(open_positions, date_rules.week_start(), time_rules.market_open())\n",
" \n",
" # At end of trading week\n",
" # 30 min before market close, dump all apple stock.\n",
" schedule_function(close_positions, date_rules.week_end(), time_rules.market_close(minutes=30))\n",
"\n",
"def open_positions(context, data):\n",
" order_target_percent(context.appl, 0.10)\n",
"\n",
"def close_positions(context, data):\n",
" order_target_percent(context.appl, 0)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Portfolio Information\n",
"\n",
"You can get portfolio information and record it!"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"def initialize(context):\n",
" context.amzn = sid(16841)\n",
" context.ibm = sid(3766)\n",
"\n",
" schedule_function(rebalance, date_rules.every_day(), time_rules.market_open())\n",
" schedule_function(record_vars, date_rules.every_day(), time_rules.market_close())\n",
"\n",
"def rebalance(context, data):\n",
" # Half of our portfolio long on amazn\n",
" order_target_percent(context.amzn, 0.50)\n",
" # Half is shorting IBM\n",
" order_target_percent(context.ibm, -0.50)\n",
"\n",
"def record_vars(context, data):\n",
"\n",
" # Plot the counts\n",
" record(amzn_close=data.current(context.amzn,'close'))\n",
" record(ibm_close=data.current(context.ibm,'close'))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Slippage and Commision \n",
"\n",
"### Slippage\n",
"Slippage is where a simulation estimates the impact of orders on the fill rate and execution price they receive. When an order is placed for a trade, the market is affected. Buy orders drive prices up, and sell orders drive prices down; this is generally referred to as the price_impact of a trade. Additionally, trade orders do not necessarily fill instantaneously. Fill rates are dependent on the order size and current trading volume of the ordered security. The volume_limit determines the fraction of a security's trading volume that can be used by your algorithm.\n",
"\n",
"In backtesting and non-brokerage paper trading (Quantopian paper trading), a slippage model can be specified in initialize() using set_slippage(). There are different builtin slippage models that can be used, as well as the option to set a custom model. By default (if a slippage model is not specified), the following volume share slippage model is used:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"set_slippage(slippage.VolumeShareSlippage(volume_limit=0.025, price_impact=0.1))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Using the default model, if an order of 60 shares is placed for a given stock, then 1000 shares of that stock trade in each of the next several minutes and the volume_limit is 0.025, then our trade order will be split into three orders (25 shares, 25 shares, and 10 shares) that execute over the next 3 minutes.\n",
"\n",
"At the end of each day, all open orders are canceled, so trading liquid stocks is generally a good idea. Additionally, orders placed exactly at market close will not have time to fill, and will be canceled."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Commision\n",
"\n",
"To set the cost of trades, we can specify a commission model in initialize() using set_commission(). By default (if a commission model is not specified), the following commission model is used:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"set_commission(commission.PerShare(cost=0.0075, min_trade_cost=1))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The default commission model charges $0.0075 per share, with a minimum trade cost of $1.\n",
"\n",
"Slippage and commission models can have an impact on the performance of a backtest. The default models used by Quantopian are fairly realistic, and it is highly recommended that you use them."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Great Job!\n",
"\n",
"Those are all the basics of Quantopians Tutorial! With these key functions you actually know enough to begin trading! "
]
}
],
"metadata": {
"anaconda-cloud": {},
"kernelspec": {
"display_name": "Python [conda root]",
"language": "python",
"name": "conda-root-py"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.5.3"
}
},
"nbformat": 4,
"nbformat_minor": 0
}