{
"cells": [
{
"cell_type": "markdown",
"id": "4ee326de",
"metadata": {},
"source": [
"\n",
"# Zipline Trading Controls 交易限制函數"
]
},
{
"cell_type": "markdown",
"id": "b1ce8e43",
"metadata": {},
"source": [
"> ## 在 Zipline 中可以加入六種不同的交易限制:\n",
"> 交易限制功能可以確保演算法如您所預期的的方式執行,並有助於避免預期外交易所帶來的不良後果。\n",
"> \n",
"> 1. [set_do_not_order_list](#set_do_not_order_list):預先設定一個不希望交易到的股票清單。\n",
"> 2. [set_long_only](#set_long_only):預先設定投資組合不能持有任何短部位(short positions)。\n",
"> 3. [set_max_leverage](#set_max_leverage):設定投資組合的槓桿限制。\n",
"> 4. [set_max_order_count](#set_max_order_count):限制一天內能夠下幾張 order。\n",
"> 5. [set_max_order_size](#set_max_order_size):限制特定股票(或全部)的單次下單股數及金額。\n",
"> 6. [set_max_position_size](#set_max_position_size):限制特定股票(或全部)在帳上的股數及市值。\n",
"> \n",
"> ## 閱讀本篇之前請先閱讀以下文章:\n",
"> \n",
"> 1. [TSMC buy and hold strategy.ipynb](https://github.com/tejtw/TQuant-Lab/blob/main/lecture/TSMC%20buy%20and%20hold%20strategy.ipynb) \n",
"> \n",
"> 2. [Zipline Order(order & order_target).ipynb](https://github.com/tejtw/TQuant-Lab/blob/main/lecture/Zipline%20Order%20(order%20%26%20order_target).ipynb)\n",
"> \n",
"> 3. [Zipline Order(value & target_value).ipynb](https://github.com/tejtw/TQuant-Lab/blob/main/lecture/Zipline%20Order%20(value%20%26%20target_value).ipynb)\n",
">\n",
"> 4. [Zipline Order(percent & target_percent).ipynb](https://github.com/tejtw/TQuant-Lab/blob/main/lecture/Zipline%20Order%20(percent%20%26%20target_percent).ipynb)\n",
">\n",
"> 5. [Zipline Slippage.ipynb](https://github.com/tejtw/TQuant-Lab/blob/main/lecture/Zipline%20Slippage.ipynb)"
]
},
{
"cell_type": "markdown",
"id": "330f2763",
"metadata": {},
"source": [
"### 補充說明:\n",
"- 交易限制系列函數通常在`initialize`階段使用。\n",
"- 可以一次加入多個交易限制。\n",
"- 因為交易限制函數皆是 zipline api 方法,需先`from zipline.api import <欲使用的方法>` 或 `from zipline.api import *`。"
]
},
{
"cell_type": "markdown",
"id": "7781a231",
"metadata": {},
"source": [
"## 設定環境"
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "2eaedc20",
"metadata": {},
"outputs": [],
"source": [
"import pandas as pd\n",
"import numpy as np\n",
"import datetime\n",
"import tejapi\n",
"import time\n",
"import os\n",
"import warnings\n",
"warnings.filterwarnings('ignore')\n",
"\n",
"# tej_key\n",
"tej_key ='your key'\n",
"tejapi.ApiConfig.api_key = tej_key\n",
"os.environ['TEJAPI_BASE'] = \"https://api.tej.com.tw\"\n",
"os.environ['TEJAPI_KEY'] = tej_key\n",
"\n",
"# date\n",
"start='2018-07-24'\n",
"end='2018-08-24'\n",
"os.environ['mdate'] = '20180724 20180824'\n",
"\n",
"tz = 'UTC'\n",
"start_dt, end_dt = pd.Timestamp(start, tz = tz), pd.Timestamp(end, tz = tz)\n",
"\n",
"# calendar\n",
"calendar_name='TEJ'\n",
"\n",
"# bundle_name\n",
"bundle_name = 'tquant'\n",
"\n",
"os.environ['ticker'] = \"2330 1216 1101 IR0001 2317 5844 2454 2357\""
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "3e71f305",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Merging daily equity files:\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"[2023-09-25 08:25:07.529281] INFO: zipline.data.bundles.core: Ingesting tquant.\n"
]
}
],
"source": [
"!zipline ingest -b tquant"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "359338d1",
"metadata": {},
"outputs": [],
"source": [
"from zipline.api import *\n",
"from zipline import run_algorithm\n",
"from zipline.finance import commission, slippage\n",
"from zipline.utils.calendar_utils import get_calendar\n",
"\n",
"from zipline.utils.run_algo import get_transaction_detail\n",
"\n",
"from logbook import Logger, StderrHandler, INFO\n",
"\n",
"# 設定log顯示方式\n",
"log_handler = StderrHandler(format_string='[{record.time:%Y-%m-%d %H:%M:%S.%f}]: ' +\n",
" '{record.level_name}: {record.func_name}: {record.message}',\n",
" level=INFO)\n",
"log_handler.push_application()\n",
"log = Logger('Algorithm')"
]
},
{
"cell_type": "markdown",
"id": "a0b6ce3d",
"metadata": {},
"source": [
"\n",
"# set_do_not_order_list\n",
"\n",
"[Return to Menu](#menu)\n",
"\n",
"### zipline.api.set_do_not_order_list(restricted_list, on_error='fail')\n",
"預先設定一個不希望交易到的股票清單\n",
"\n",
"\n",
"- restricted_list (*container[Asset], SecurityList*)\n",
" - 預先限制不能交易的股票清單。\n",
" - container 中必須是`Asset`物件(`zipline.assets.Asset`,例如:Equity(0 [1101]),透過`symbol(\"1101\")`可將 symbol 轉成`Asset`物件)\n",
" \n",
"\n",
"- on_error (*str, optional*):\n",
" - on_error有兩種選項:'fail' 和 'log'。前者直接中斷程式並顯示錯誤訊息,後者會照樣執行但記錄錯誤。預設為'fail'。\n",
" - 若要使用on_error = 'log',請同時進行以下設定,才能顯示 log:\n",
"\n",
" ```python\n",
" from logbook import Logger, StderrHandler, INFO\n",
" # 設定log顯示方式\n",
" log_handler = StderrHandler(format_string='[{record.time:%Y-%m-%d %H:%M:%S.%f}]: ' +\n",
" '{record.level_name}: {record.func_name}: {record.message}',\n",
" level=INFO)\n",
" log_handler.push_application()\n",
" log = Logger('Algorithm')\n",
" ```\n",
" \n",
"#### 範例1\n",
"\n",
"在以下程式中,我們把 **1101 加入限制清單**,**on_error(發生時處理方法)使用'log'**,然後設定在7/26下單。\n",
"```python\n",
"def initialize(context):\n",
" ...\n",
" set_do_not_order_list(restricted_list = [symbol('1101')], on_error='log')\n",
" ...\n",
"\n",
"def handle_data(context, data): \n",
" ...\n",
" if context.i == 2: # 2018-07-26\n",
" order(symbol('1101'), 100)\n",
" ...\n",
"``` \n",
" \n",
"可以看到執行時跳出\n",
"```\n",
"ERROR: handle_violation: Order for 100 shares of Equity(0 [1101]) at 2018-07-26 05:30:00+00:00 violates trading constraint RestrictedListOrder({})\n",
"```\n",
" \n",
"但是觀察 transactions ,可以發現7/27時照樣買入了 1101。"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "a97e1867",
"metadata": {
"scrolled": true
},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"[2023-09-25 08:25:09.801010]: ERROR: handle_violation: Order for 100 shares of Equity(0 [1101]) at 2018-07-26 05:30:00+00:00 violates trading constraint RestrictedListOrder({})\n",
"[2023-09-25 08:25:09.812006]: INFO: earn_dividends: Equity(1 [1216]), cash_dividend amount: 5.5, pay_date: 2018-09-07, div_owed: 550.0\n",
"[2023-09-25 08:25:09.841082]: INFO: handle_simulation_end: Simulated 24 trading days\n",
"first open: 2018-07-24 01:01:00+00:00\n",
"last close: 2018-08-24 05:30:00+00:00\n"
]
}
],
"source": [
"def initialize(context):\n",
" context.i = 0\n",
" set_do_not_order_list(restricted_list = [symbol('1101')], on_error='log')\n",
" set_slippage(slippage.FixedSlippage(spread = 0.0))\n",
" set_commission(commission.PerDollar(cost=commission_cost))\n",
" set_benchmark(symbol('IR0001'))\n",
" \n",
"def handle_data(context, data):\n",
" \n",
" if context.i == 0: # 2018-07-24\n",
" order(symbol('2330'), 100)\n",
" \n",
" if context.i == 2: # 2018-07-26\n",
" order(symbol('1101'), 100)\n",
"\n",
" if context.i == 4: # 2018-07-30\n",
" order(symbol('1216'), 100)\n",
" \n",
" context.i += 1\n",
" \n",
"\n",
"commission_cost = 0.001425\n",
"capital_base = 1e6\n",
"\n",
"performance = run_algorithm(start=start_dt,\n",
" end=end_dt,\n",
" initialize=initialize,\n",
" handle_data=handle_data,\n",
" capital_base=capital_base,\n",
" trading_calendar=get_calendar(calendar_name),\n",
" bundle=bundle_name)\n",
"\n",
"positions, transactions, orders = get_transaction_detail(performance)"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "d5bf41da",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"
\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" sid | \n",
" symbol | \n",
" amount | \n",
" dt | \n",
" price | \n",
" order_id | \n",
" asset | \n",
" commission | \n",
"
\n",
" \n",
" \n",
" \n",
" 2018-07-25 13:30:00+08:00 | \n",
" 3 | \n",
" 2330 | \n",
" 100 | \n",
" 2018-07-25 13:30:00+08:00 | \n",
" 240.5 | \n",
" f1148fd31aa84be5b4d7e27c9c858a39 | \n",
" Equity(3 [2330]) | \n",
" None | \n",
"
\n",
" \n",
" 2018-07-27 13:30:00+08:00 | \n",
" 0 | \n",
" 1101 | \n",
" 100 | \n",
" 2018-07-27 13:30:00+08:00 | \n",
" 40.3 | \n",
" d4971027bce4491db4eeb0cf8655c4bc | \n",
" Equity(0 [1101]) | \n",
" None | \n",
"
\n",
" \n",
" 2018-07-31 13:30:00+08:00 | \n",
" 1 | \n",
" 1216 | \n",
" 100 | \n",
" 2018-07-31 13:30:00+08:00 | \n",
" 80.8 | \n",
" ac333a81f710428e83c5ccacc8ce72e2 | \n",
" Equity(1 [1216]) | \n",
" None | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" sid symbol amount dt \\\n",
"2018-07-25 13:30:00+08:00 3 2330 100 2018-07-25 13:30:00+08:00 \n",
"2018-07-27 13:30:00+08:00 0 1101 100 2018-07-27 13:30:00+08:00 \n",
"2018-07-31 13:30:00+08:00 1 1216 100 2018-07-31 13:30:00+08:00 \n",
"\n",
" price order_id \\\n",
"2018-07-25 13:30:00+08:00 240.5 f1148fd31aa84be5b4d7e27c9c858a39 \n",
"2018-07-27 13:30:00+08:00 40.3 d4971027bce4491db4eeb0cf8655c4bc \n",
"2018-07-31 13:30:00+08:00 80.8 ac333a81f710428e83c5ccacc8ce72e2 \n",
"\n",
" asset commission \n",
"2018-07-25 13:30:00+08:00 Equity(3 [2330]) None \n",
"2018-07-27 13:30:00+08:00 Equity(0 [1101]) None \n",
"2018-07-31 13:30:00+08:00 Equity(1 [1216]) None "
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# 7/27 照樣買入了1101。\n",
"transactions"
]
},
{
"cell_type": "markdown",
"id": "90e36fea",
"metadata": {},
"source": [
"#### 範例2\n",
"但如果 **on_error 設定成 'fail'**,整個程式會被中止,然後顯示一樣的錯誤訊息。\n",
"\n",
"```python\n",
"set_do_not_order_list(restricted_list = [symbol('1101')], on_error='fail')\n",
"```"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "7c707fb2",
"metadata": {},
"outputs": [
{
"ename": "TradingControlViolation",
"evalue": "Order for 100 shares of Equity(0 [1101]) at 2018-07-26 05:30:00+00:00 violates trading constraint\nRestrictedListOrder({}).",
"output_type": "error",
"traceback": [
"\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[1;31mTradingControlViolation\u001b[0m Traceback (most recent call last)",
"Input \u001b[1;32mIn [6]\u001b[0m, in \u001b[0;36m\u001b[1;34m()\u001b[0m\n\u001b[0;32m 22\u001b[0m commission_cost \u001b[38;5;241m=\u001b[39m \u001b[38;5;241m0.001425\u001b[39m\n\u001b[0;32m 23\u001b[0m capital_base \u001b[38;5;241m=\u001b[39m \u001b[38;5;241m1e6\u001b[39m\n\u001b[1;32m---> 25\u001b[0m performance \u001b[38;5;241m=\u001b[39m \u001b[43mrun_algorithm\u001b[49m\u001b[43m(\u001b[49m\u001b[43mstart\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mstart_dt\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 26\u001b[0m \u001b[43m \u001b[49m\u001b[43mend\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mend_dt\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 27\u001b[0m \u001b[43m \u001b[49m\u001b[43minitialize\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43minitialize\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 28\u001b[0m \u001b[43m \u001b[49m\u001b[43mhandle_data\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mhandle_data\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 29\u001b[0m \u001b[43m \u001b[49m\u001b[43mcapital_base\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mcapital_base\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 30\u001b[0m \u001b[43m \u001b[49m\u001b[43mtrading_calendar\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mget_calendar\u001b[49m\u001b[43m(\u001b[49m\u001b[43mcalendar_name\u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 31\u001b[0m \u001b[43m \u001b[49m\u001b[43mbundle\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mbundle_name\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 33\u001b[0m positions, transactions, orders \u001b[38;5;241m=\u001b[39m get_transaction_detail(performance)\n",
"File \u001b[1;32m~\\Anaconda3\\envs\\zipline-tej\\lib\\site-packages\\zipline\\utils\\run_algo.py:446\u001b[0m, in \u001b[0;36mrun_algorithm\u001b[1;34m(start, end, initialize, capital_base, handle_data, before_trading_start, analyze, data_frequency, bundle, bundle_timestamp, trading_calendar, metrics_set, benchmark_returns, treasury_returns, default_extension, extensions, strict_extensions, environ, custom_loader, blotter)\u001b[0m\n\u001b[0;32m 443\u001b[0m benchmark_spec \u001b[38;5;241m=\u001b[39m BenchmarkSpec\u001b[38;5;241m.\u001b[39mfrom_returns(benchmark_returns) \n\u001b[0;32m 444\u001b[0m treasury_spec \u001b[38;5;241m=\u001b[39m TreasurySpec\u001b[38;5;241m.\u001b[39mfrom_returns(treasury_returns) \u001b[38;5;66;03m#20230210(by MRC) for treasury return column in perf\u001b[39;00m\n\u001b[1;32m--> 446\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43m_run\u001b[49m\u001b[43m(\u001b[49m\n\u001b[0;32m 447\u001b[0m \u001b[43m \u001b[49m\u001b[43mhandle_data\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mhandle_data\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 448\u001b[0m \u001b[43m \u001b[49m\u001b[43minitialize\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43minitialize\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 449\u001b[0m \u001b[43m \u001b[49m\u001b[43mbefore_trading_start\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mbefore_trading_start\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 450\u001b[0m \u001b[43m \u001b[49m\u001b[43manalyze\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43manalyze\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 451\u001b[0m \u001b[43m \u001b[49m\u001b[43malgofile\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mNone\u001b[39;49;00m\u001b[43m,\u001b[49m\n\u001b[0;32m 452\u001b[0m \u001b[43m \u001b[49m\u001b[43malgotext\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mNone\u001b[39;49;00m\u001b[43m,\u001b[49m\n\u001b[0;32m 453\u001b[0m \u001b[43m \u001b[49m\u001b[43mdefines\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 454\u001b[0m \u001b[43m \u001b[49m\u001b[43mdata_frequency\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mdata_frequency\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 455\u001b[0m \u001b[43m \u001b[49m\u001b[43mcapital_base\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mcapital_base\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 456\u001b[0m \u001b[43m \u001b[49m\u001b[43mbundle\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mbundle\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 457\u001b[0m \u001b[43m \u001b[49m\u001b[43mbundle_timestamp\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mbundle_timestamp\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 458\u001b[0m \u001b[43m \u001b[49m\u001b[43mstart\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mstart\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 459\u001b[0m \u001b[43m \u001b[49m\u001b[43mend\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mend\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 460\u001b[0m \u001b[43m \u001b[49m\u001b[43moutput\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mos\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mdevnull\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 461\u001b[0m \u001b[43m \u001b[49m\u001b[43mtrading_calendar\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mtrading_calendar\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 462\u001b[0m \u001b[43m \u001b[49m\u001b[43mprint_algo\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mFalse\u001b[39;49;00m\u001b[43m,\u001b[49m\n\u001b[0;32m 463\u001b[0m \u001b[43m \u001b[49m\u001b[43mmetrics_set\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mmetrics_set\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 464\u001b[0m \u001b[43m \u001b[49m\u001b[43mlocal_namespace\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mFalse\u001b[39;49;00m\u001b[43m,\u001b[49m\n\u001b[0;32m 465\u001b[0m \u001b[43m \u001b[49m\u001b[43menviron\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43menviron\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 466\u001b[0m \u001b[43m \u001b[49m\u001b[43mblotter\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mblotter\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 467\u001b[0m \u001b[43m \u001b[49m\u001b[43mcustom_loader\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mcustom_loader\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 468\u001b[0m \u001b[43m \u001b[49m\u001b[43mbenchmark_spec\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mbenchmark_spec\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 469\u001b[0m \u001b[43m \u001b[49m\u001b[43mtreasury_spec\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mtreasury_spec\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;66;43;03m#20230209 (by MRC) for treasury return column in perf\u001b[39;49;00m\n\u001b[0;32m 470\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n",
"File \u001b[1;32m~\\Anaconda3\\envs\\zipline-tej\\lib\\site-packages\\zipline\\utils\\run_algo.py:225\u001b[0m, in \u001b[0;36m_run\u001b[1;34m(handle_data, initialize, before_trading_start, analyze, algofile, algotext, defines, data_frequency, capital_base, bundle, bundle_timestamp, start, end, output, trading_calendar, print_algo, metrics_set, local_namespace, environ, blotter, custom_loader, benchmark_spec, treasury_spec)\u001b[0m\n\u001b[0;32m 222\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m _RunAlgoError(\u001b[38;5;28mstr\u001b[39m(e))\n\u001b[0;32m 224\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m--> 225\u001b[0m perf \u001b[38;5;241m=\u001b[39m \u001b[43mTradingAlgorithm\u001b[49m\u001b[43m(\u001b[49m\n\u001b[0;32m 226\u001b[0m \u001b[43m \u001b[49m\u001b[43mnamespace\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mnamespace\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 227\u001b[0m \u001b[43m \u001b[49m\u001b[43mdata_portal\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mdata\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 228\u001b[0m \u001b[43m \u001b[49m\u001b[43mget_pipeline_loader\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mchoose_loader\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 229\u001b[0m \u001b[43m \u001b[49m\u001b[43mtrading_calendar\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mtrading_calendar\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 230\u001b[0m \u001b[43m \u001b[49m\u001b[43msim_params\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mSimulationParameters\u001b[49m\u001b[43m(\u001b[49m\n\u001b[0;32m 231\u001b[0m \u001b[43m \u001b[49m\u001b[43mstart_session\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mstart\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 232\u001b[0m \u001b[43m \u001b[49m\u001b[43mend_session\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mend\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 233\u001b[0m \u001b[43m \u001b[49m\u001b[43mtrading_calendar\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mtrading_calendar\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 234\u001b[0m \u001b[43m \u001b[49m\u001b[43mcapital_base\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mcapital_base\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 235\u001b[0m \u001b[43m \u001b[49m\u001b[43mdata_frequency\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mdata_frequency\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 236\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 237\u001b[0m \u001b[43m \u001b[49m\u001b[43mmetrics_set\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mmetrics_set\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 238\u001b[0m \u001b[43m \u001b[49m\u001b[43mblotter\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mblotter\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 239\u001b[0m \u001b[43m \u001b[49m\u001b[43mbenchmark_returns\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mbenchmark_returns\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 240\u001b[0m \u001b[43m \u001b[49m\u001b[43mbenchmark_sid\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mbenchmark_sid\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 241\u001b[0m \u001b[43m \u001b[49m\u001b[43mtreasury_returns\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mtreasury_returns\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;66;43;03m#20230209 (by MRC) for treasury return column in perf\u001b[39;49;00m\n\u001b[0;32m 242\u001b[0m \u001b[43m \u001b[49m\u001b[43mtreasury_sid\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mtreasury_sid\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;66;43;03m#20230209 (by MRC) for treasury return column in perf\u001b[39;49;00m\n\u001b[0;32m 243\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43m{\u001b[49m\n\u001b[0;32m 244\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43minitialize\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m:\u001b[49m\u001b[43m \u001b[49m\u001b[43minitialize\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 245\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mhandle_data\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m:\u001b[49m\u001b[43m \u001b[49m\u001b[43mhandle_data\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 246\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mbefore_trading_start\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m:\u001b[49m\u001b[43m \u001b[49m\u001b[43mbefore_trading_start\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 247\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43manalyze\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m:\u001b[49m\u001b[43m \u001b[49m\u001b[43manalyze\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 248\u001b[0m \u001b[43m \u001b[49m\u001b[43m}\u001b[49m\n\u001b[0;32m 249\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43;01mif\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43malgotext\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;129;43;01mis\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[38;5;28;43;01mNone\u001b[39;49;00m\n\u001b[0;32m 250\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43;01melse\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43m{\u001b[49m\n\u001b[0;32m 251\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43malgo_filename\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m:\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43mgetattr\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43malgofile\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mname\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43m\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 252\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mscript\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m:\u001b[49m\u001b[43m \u001b[49m\u001b[43malgotext\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 253\u001b[0m \u001b[43m \u001b[49m\u001b[43m}\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 254\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mrun\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 257\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m NoBenchmark:\n\u001b[0;32m 258\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m _RunAlgoError(\n\u001b[0;32m 259\u001b[0m (\n\u001b[0;32m 260\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mNo ``benchmark_spec`` was provided, and\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m (...)\u001b[0m\n\u001b[0;32m 268\u001b[0m ),\n\u001b[0;32m 269\u001b[0m )\n",
"File \u001b[1;32m~\\Anaconda3\\envs\\zipline-tej\\lib\\site-packages\\zipline\\algorithm.py:685\u001b[0m, in \u001b[0;36mTradingAlgorithm.run\u001b[1;34m(self, data_portal)\u001b[0m\n\u001b[0;32m 683\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m 684\u001b[0m perfs \u001b[38;5;241m=\u001b[39m []\n\u001b[1;32m--> 685\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m perf \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mget_generator():\n\u001b[0;32m 686\u001b[0m perfs\u001b[38;5;241m.\u001b[39mappend(perf)\n\u001b[0;32m 688\u001b[0m \u001b[38;5;66;03m# convert perf dict to pandas dataframe\u001b[39;00m\n",
"File \u001b[1;32m~\\Anaconda3\\envs\\zipline-tej\\lib\\site-packages\\zipline\\gens\\tradesimulation.py:230\u001b[0m, in \u001b[0;36mAlgorithmSimulator.transform\u001b[1;34m(self)\u001b[0m\n\u001b[0;32m 228\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m dt, action \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mclock:\n\u001b[0;32m 229\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m action \u001b[38;5;241m==\u001b[39m BAR:\n\u001b[1;32m--> 230\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m capital_change_packet \u001b[38;5;129;01min\u001b[39;00m every_bar(dt):\n\u001b[0;32m 231\u001b[0m \u001b[38;5;28;01myield\u001b[39;00m capital_change_packet\n\u001b[0;32m 232\u001b[0m \u001b[38;5;28;01melif\u001b[39;00m action \u001b[38;5;241m==\u001b[39m SESSION_START:\n",
"File \u001b[1;32m~\\Anaconda3\\envs\\zipline-tej\\lib\\site-packages\\zipline\\gens\\tradesimulation.py:144\u001b[0m, in \u001b[0;36mAlgorithmSimulator.transform..every_bar\u001b[1;34m(dt_to_use, current_data, handle_data)\u001b[0m\n\u001b[0;32m 141\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m commission \u001b[38;5;129;01min\u001b[39;00m new_commissions:\n\u001b[0;32m 142\u001b[0m metrics_tracker\u001b[38;5;241m.\u001b[39mprocess_commission(commission)\n\u001b[1;32m--> 144\u001b[0m \u001b[43mhandle_data\u001b[49m\u001b[43m(\u001b[49m\u001b[43malgo\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mcurrent_data\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mdt_to_use\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 146\u001b[0m \u001b[38;5;66;03m# grab any new orders from the blotter, then clear the list.\u001b[39;00m\n\u001b[0;32m 147\u001b[0m \u001b[38;5;66;03m# this includes cancelled orders.\u001b[39;00m\n\u001b[0;32m 148\u001b[0m new_orders \u001b[38;5;241m=\u001b[39m blotter\u001b[38;5;241m.\u001b[39mnew_orders\n",
"File \u001b[1;32m~\\Anaconda3\\envs\\zipline-tej\\lib\\site-packages\\zipline\\utils\\events.py:206\u001b[0m, in \u001b[0;36mEventManager.handle_data\u001b[1;34m(self, context, data, dt)\u001b[0m\n\u001b[0;32m 204\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_create_context(data):\n\u001b[0;32m 205\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m event \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_events:\n\u001b[1;32m--> 206\u001b[0m \u001b[43mevent\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mhandle_data\u001b[49m\u001b[43m(\u001b[49m\n\u001b[0;32m 207\u001b[0m \u001b[43m \u001b[49m\u001b[43mcontext\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 208\u001b[0m \u001b[43m \u001b[49m\u001b[43mdata\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 209\u001b[0m \u001b[43m \u001b[49m\u001b[43mdt\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 210\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n",
"File \u001b[1;32m~\\Anaconda3\\envs\\zipline-tej\\lib\\site-packages\\zipline\\utils\\events.py:229\u001b[0m, in \u001b[0;36mEvent.handle_data\u001b[1;34m(self, context, data, dt)\u001b[0m\n\u001b[0;32m 225\u001b[0m \u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[0;32m 226\u001b[0m \u001b[38;5;124;03mCalls the callable only when the rule is triggered.\u001b[39;00m\n\u001b[0;32m 227\u001b[0m \u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[0;32m 228\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mrule\u001b[38;5;241m.\u001b[39mshould_trigger(dt):\n\u001b[1;32m--> 229\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mcallback\u001b[49m\u001b[43m(\u001b[49m\u001b[43mcontext\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mdata\u001b[49m\u001b[43m)\u001b[49m\n",
"File \u001b[1;32m~\\Anaconda3\\envs\\zipline-tej\\lib\\site-packages\\zipline\\algorithm.py:477\u001b[0m, in \u001b[0;36mTradingAlgorithm.handle_data\u001b[1;34m(self, data)\u001b[0m\n\u001b[0;32m 475\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mhandle_data\u001b[39m(\u001b[38;5;28mself\u001b[39m, data):\n\u001b[0;32m 476\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_handle_data:\n\u001b[1;32m--> 477\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_handle_data\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mdata\u001b[49m\u001b[43m)\u001b[49m\n",
"Input \u001b[1;32mIn [6]\u001b[0m, in \u001b[0;36mhandle_data\u001b[1;34m(context, data)\u001b[0m\n\u001b[0;32m 11\u001b[0m order(symbol(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m2330\u001b[39m\u001b[38;5;124m'\u001b[39m), \u001b[38;5;241m100\u001b[39m)\n\u001b[0;32m 13\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m context\u001b[38;5;241m.\u001b[39mi \u001b[38;5;241m==\u001b[39m \u001b[38;5;241m2\u001b[39m: \u001b[38;5;66;03m# 2018-07-26\u001b[39;00m\n\u001b[1;32m---> 14\u001b[0m \u001b[43morder\u001b[49m\u001b[43m(\u001b[49m\u001b[43msymbol\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43m1101\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m100\u001b[39;49m\u001b[43m)\u001b[49m\n\u001b[0;32m 16\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m context\u001b[38;5;241m.\u001b[39mi \u001b[38;5;241m==\u001b[39m \u001b[38;5;241m4\u001b[39m: \u001b[38;5;66;03m# 2018-07-30\u001b[39;00m\n\u001b[0;32m 17\u001b[0m order(symbol(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m1216\u001b[39m\u001b[38;5;124m'\u001b[39m), \u001b[38;5;241m100\u001b[39m)\n",
"File \u001b[1;32m~\\Anaconda3\\envs\\zipline-tej\\lib\\site-packages\\zipline\\utils\\api_support.py:55\u001b[0m, in \u001b[0;36mapi_method..wrapped\u001b[1;34m(*args, **kwargs)\u001b[0m\n\u001b[0;32m 51\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m algo_instance \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[0;32m 52\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mRuntimeError\u001b[39;00m(\n\u001b[0;32m 53\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mzipline api method \u001b[39m\u001b[38;5;132;01m%s\u001b[39;00m\u001b[38;5;124m must be called during a simulation.\u001b[39m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;241m%\u001b[39m f\u001b[38;5;241m.\u001b[39m\u001b[38;5;18m__name__\u001b[39m\n\u001b[0;32m 54\u001b[0m )\n\u001b[1;32m---> 55\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mgetattr\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43malgo_instance\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mf\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[38;5;18;43m__name__\u001b[39;49m\u001b[43m)\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n",
"File \u001b[1;32m~\\Anaconda3\\envs\\zipline-tej\\lib\\site-packages\\zipline\\utils\\api_support.py:132\u001b[0m, in \u001b[0;36mdisallowed_in_before_trading_start..decorator..wrapped_method\u001b[1;34m(self, *args, **kwargs)\u001b[0m\n\u001b[0;32m 130\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_in_before_trading_start:\n\u001b[0;32m 131\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m exception\n\u001b[1;32m--> 132\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mmethod\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n",
"File \u001b[1;32m~\\Anaconda3\\envs\\zipline-tej\\lib\\site-packages\\zipline\\algorithm.py:1447\u001b[0m, in \u001b[0;36mTradingAlgorithm.order\u001b[1;34m(self, asset, amount, limit_price, stop_price, style)\u001b[0m\n\u001b[0;32m 1444\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_can_order_asset(asset):\n\u001b[0;32m 1445\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[1;32m-> 1447\u001b[0m amount, style \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_calculate_order\u001b[49m\u001b[43m(\u001b[49m\n\u001b[0;32m 1448\u001b[0m \u001b[43m \u001b[49m\u001b[43masset\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mamount\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mlimit_price\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mstop_price\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mstyle\u001b[49m\n\u001b[0;32m 1449\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 1450\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mblotter\u001b[38;5;241m.\u001b[39morder(asset, amount, style)\n",
"File \u001b[1;32m~\\Anaconda3\\envs\\zipline-tej\\lib\\site-packages\\zipline\\algorithm.py:1458\u001b[0m, in \u001b[0;36mTradingAlgorithm._calculate_order\u001b[1;34m(self, asset, amount, limit_price, stop_price, style)\u001b[0m\n\u001b[0;32m 1455\u001b[0m amount \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mround_order(amount)\n\u001b[0;32m 1457\u001b[0m \u001b[38;5;66;03m# Raises a ZiplineError if invalid parameters are detected.\u001b[39;00m\n\u001b[1;32m-> 1458\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mvalidate_order_params\u001b[49m\u001b[43m(\u001b[49m\u001b[43masset\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mamount\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mlimit_price\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mstop_price\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mstyle\u001b[49m\u001b[43m)\u001b[49m\n\u001b[0;32m 1460\u001b[0m \u001b[38;5;66;03m# Convert deprecated limit_price and stop_price parameters to use\u001b[39;00m\n\u001b[0;32m 1461\u001b[0m \u001b[38;5;66;03m# ExecutionStyle objects.\u001b[39;00m\n\u001b[0;32m 1462\u001b[0m style \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m__convert_order_params_for_blotter(\n\u001b[0;32m 1463\u001b[0m asset, limit_price, stop_price, style\n\u001b[0;32m 1464\u001b[0m )\n",
"File \u001b[1;32m~\\Anaconda3\\envs\\zipline-tej\\lib\\site-packages\\zipline\\algorithm.py:1503\u001b[0m, in \u001b[0;36mTradingAlgorithm.validate_order_params\u001b[1;34m(self, asset, amount, limit_price, stop_price, style)\u001b[0m\n\u001b[0;32m 1498\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m UnsupportedOrderParameters(\n\u001b[0;32m 1499\u001b[0m msg\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mPassing both stop_price and style is not supported.\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m 1500\u001b[0m )\n\u001b[0;32m 1502\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m control \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mtrading_controls:\n\u001b[1;32m-> 1503\u001b[0m \u001b[43mcontrol\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mvalidate\u001b[49m\u001b[43m(\u001b[49m\n\u001b[0;32m 1504\u001b[0m \u001b[43m \u001b[49m\u001b[43masset\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 1505\u001b[0m \u001b[43m \u001b[49m\u001b[43mamount\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 1506\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mportfolio\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 1507\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mget_datetime\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 1508\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mtrading_client\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mcurrent_data\u001b[49m\u001b[43m,\u001b[49m\n\u001b[0;32m 1509\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n",
"File \u001b[1;32m~\\Anaconda3\\envs\\zipline-tej\\lib\\site-packages\\zipline\\finance\\controls.py:149\u001b[0m, in \u001b[0;36mRestrictedListOrder.validate\u001b[1;34m(self, asset, amount, portfolio, algo_datetime, algo_current_data)\u001b[0m\n\u001b[0;32m 145\u001b[0m \u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[0;32m 146\u001b[0m \u001b[38;5;124;03mFail if the asset is in the restricted_list.\u001b[39;00m\n\u001b[0;32m 147\u001b[0m \u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[0;32m 148\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mrestrictions\u001b[38;5;241m.\u001b[39mis_restricted(asset, algo_datetime):\n\u001b[1;32m--> 149\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mhandle_violation\u001b[49m\u001b[43m(\u001b[49m\u001b[43masset\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mamount\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43malgo_datetime\u001b[49m\u001b[43m)\u001b[49m\n",
"File \u001b[1;32m~\\Anaconda3\\envs\\zipline-tej\\lib\\site-packages\\zipline\\finance\\controls.py:82\u001b[0m, in \u001b[0;36mTradingControl.handle_violation\u001b[1;34m(self, asset, amount, datetime, metadata)\u001b[0m\n\u001b[0;32m 79\u001b[0m constraint \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_constraint_msg(metadata)\n\u001b[0;32m 81\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mon_error \u001b[38;5;241m==\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mfail\u001b[39m\u001b[38;5;124m\"\u001b[39m:\n\u001b[1;32m---> 82\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m TradingControlViolation(\n\u001b[0;32m 83\u001b[0m asset\u001b[38;5;241m=\u001b[39masset, amount\u001b[38;5;241m=\u001b[39mamount, datetime\u001b[38;5;241m=\u001b[39mdatetime, constraint\u001b[38;5;241m=\u001b[39mconstraint\n\u001b[0;32m 84\u001b[0m )\n\u001b[0;32m 85\u001b[0m \u001b[38;5;28;01melif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mon_error \u001b[38;5;241m==\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mlog\u001b[39m\u001b[38;5;124m\"\u001b[39m:\n\u001b[0;32m 86\u001b[0m log\u001b[38;5;241m.\u001b[39merror(\n\u001b[0;32m 87\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mOrder for \u001b[39m\u001b[38;5;132;01m{amount}\u001b[39;00m\u001b[38;5;124m shares of \u001b[39m\u001b[38;5;132;01m{asset}\u001b[39;00m\u001b[38;5;124m at \u001b[39m\u001b[38;5;132;01m{dt}\u001b[39;00m\u001b[38;5;124m \u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m 88\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mviolates trading constraint \u001b[39m\u001b[38;5;132;01m{constraint}\u001b[39;00m\u001b[38;5;124m\"\u001b[39m,\n\u001b[1;32m (...)\u001b[0m\n\u001b[0;32m 92\u001b[0m constraint\u001b[38;5;241m=\u001b[39mconstraint,\n\u001b[0;32m 93\u001b[0m )\n",
"\u001b[1;31mTradingControlViolation\u001b[0m: Order for 100 shares of Equity(0 [1101]) at 2018-07-26 05:30:00+00:00 violates trading constraint\nRestrictedListOrder({})."
]
}
],
"source": [
"def initialize(context):\n",
" context.i = 0\n",
" set_do_not_order_list(restricted_list = [symbol('1101')], on_error='fail')\n",
" set_slippage(slippage.FixedSlippage(spread = 0.0))\n",
" set_commission(commission.PerDollar(cost=commission_cost))\n",
" set_benchmark(symbol('IR0001'))\n",
" \n",
"def handle_data(context, data):\n",
" \n",
" if context.i == 0: # 2018-07-24\n",
" order(symbol('2330'), 100)\n",
" \n",
" if context.i == 2: # 2018-07-26\n",
" order(symbol('1101'), 100)\n",
"\n",
" if context.i == 4: # 2018-07-30\n",
" order(symbol('1216'), 100)\n",
" \n",
" context.i += 1\n",
"\n",
"\n",
"commission_cost = 0.001425\n",
"capital_base = 1e6\n",
"\n",
"performance = run_algorithm(start=start_dt,\n",
" end=end_dt,\n",
" initialize=initialize,\n",
" handle_data=handle_data,\n",
" capital_base=capital_base,\n",
" trading_calendar=get_calendar(calendar_name),\n",
" bundle=bundle_name)\n",
"\n",
"positions, transactions, orders = get_transaction_detail(performance)"
]
},
{
"cell_type": "markdown",
"id": "e7ed7c48",
"metadata": {},
"source": [
"\n",
"# set_long_only\n",
"預先設定投資組合**不能**持有任何**短部位(short positions)**\n",
"\n",
"[Return to Menu](#menu)\n",
"\n",
"### zipline.api.set_long_only(on_error='fail')\n",
"\n",
"on_error (*str, optional*):\n",
"- on_error有兩種選項:'fail' 和 'log'。前者直接中斷程式並顯示錯誤訊息,後者會照樣執行但記錄錯誤。預設為'fail'。\n",
"- 若要使用on_error = 'log',請同時進行以下設定,才能顯示 log:\n",
"\n",
"```python\n",
"from logbook import Logger, StderrHandler, INFO\n",
"# 設定log顯示方式\n",
"log_handler = StderrHandler(format_string='[{record.time:%Y-%m-%d %H:%M:%S.%f}]: ' +\n",
" '{record.level_name}: {record.func_name}: {record.message}',\n",
" level=INFO)\n",
"log_handler.push_application()\n",
"log = Logger('Algorithm')\n",
"```\n",
"\n",
" \n",
"\n",
"#### 範例\n",
"- 在以下這個範例我們設定`set_long_only(on_error='log')`,並且在7/24買入 1000 股 2330 股票、7/26賣出 500 股 2330 股票且在7/30賣出 800 股 2330 股票。\n",
"\n",
"```python\n",
"def initialize(context):\n",
" ...\n",
" set_long_only(on_error='log')\n",
" ...\n",
" \n",
"def handle_data(context, data): \n",
" if context.i == 0: # 7/24\n",
" order(symbol('2330'), 1000)\n",
"\n",
" if context.i == 2: # 7/26 \n",
" order(symbol('2330'), -500)\n",
"\n",
" if context.i == 4: # 7/30\n",
" order(symbol('2330'), -800)\n",
" ...\n",
"```\n",
"\n",
"- 當帳上持有 1000 股時賣出 500 股(7/26)是不會有問題的,但是如果再賣出 800 股(7/30),就會變成 - 300 股(short position),所以就會跳出了警示:\n",
"```python\n",
"ERROR: handle_violation: Order for -800 shares of Equity(14 [2330]) at 2018-07-30 05:30:00+00:00 violates trading \n",
"constraint LongOnly({})\n",
"```\n",
"但因為 on_error 設定是 'log',股票依然成功賣出。"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "08acbcfa",
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"[2023-09-25 08:25:16.371644]: ERROR: handle_violation: Order for -800 shares of Equity(3 [2330]) at 2018-07-30 05:30:00+00:00 violates trading constraint LongOnly({})\n",
"[2023-09-25 08:25:16.395643]: INFO: handle_simulation_end: Simulated 24 trading days\n",
"first open: 2018-07-24 01:01:00+00:00\n",
"last close: 2018-08-24 05:30:00+00:00\n"
]
}
],
"source": [
"def initialize(context):\n",
" context.i = 0\n",
" set_long_only(on_error='log')\n",
" set_slippage(slippage.FixedSlippage(spread = 0.0))\n",
" set_commission(commission.PerDollar(cost=commission_cost))\n",
" set_benchmark(symbol('IR0001'))\n",
" \n",
"def handle_data(context, data):\n",
" \n",
" if context.i == 0: # 7/24\n",
" order(symbol('2330'), 1000)\n",
" \n",
" if context.i == 2: # 7/26 \n",
" order(symbol('2330'), -500)\n",
"\n",
" if context.i == 4: # 7/30\n",
" order(symbol('2330'), -800)\n",
" \n",
" context.i += 1\n",
" \n",
"commission_cost = 0.001425\n",
"capital_base = 1e6\n",
"\n",
"performance = run_algorithm(start=start_dt,\n",
" end=end_dt,\n",
" initialize=initialize,\n",
" handle_data=handle_data,\n",
" capital_base=capital_base,\n",
" trading_calendar=get_calendar(calendar_name),\n",
" bundle=bundle_name)\n",
"\n",
"positions, transactions, orders = get_transaction_detail(performance)"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "2b3d5846",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
" \n",
" \n",
" \n",
" | \n",
" sid | \n",
" symbol | \n",
" asset | \n",
" amount | \n",
" cost_basis | \n",
" last_sale_price | \n",
" \n",
" \n",
" \n",
" \n",
" 2018-07-25 13:30:00+08:00 | \n",
" 3 | \n",
" 2330 | \n",
" Equity(3 [2330]) | \n",
" 1000 | \n",
" 240.842713 | \n",
" 240.5 | \n",
" \n",
" \n",
" 2018-07-26 13:30:00+08:00 | \n",
" 3 | \n",
" 2330 | \n",
" Equity(3 [2330]) | \n",
" 1000 | \n",
" 240.842713 | \n",
" 241.0 | \n",
" \n",
" \n",
" 2018-07-27 13:30:00+08:00 | \n",
" 3 | \n",
" 2330 | \n",
" Equity(3 [2330]) | \n",
" 500 | \n",
" 241.191125 | \n",
" 244.5 | \n",
" \n",
" \n",
" 2018-07-30 13:30:00+08:00 | \n",
" 3 | \n",
" 2330 | \n",
" Equity(3 [2330]) | \n",
" 500 | \n",
" 241.191125 | \n",
" 245.5 | \n",
" \n",
" \n",
" 2018-07-31 13:30:00+08:00 | \n",
" 3 | \n",
" 2330 | \n",
" Equity(3 [2330]) | \n",
" -300 | \n",
" 245.065200 | \n",
" 246.0 | \n",
" \n",
" \n",
" 2018-08-01 13:30:00+08:00 | \n",
" 3 | \n",
" 2330 | \n",
" Equity(3 [2330]) | \n",
" -300 | \n",
" 245.065200 | \n",
" 248.0 | \n",
" \n",
" \n",
" \n",
" "
],
"text/plain": [
" sid symbol asset amount cost_basis \\\n",
"2018-07-25 13:30:00+08:00 3 2330 Equity(3 [2330]) 1000 240.842713 \n",
"2018-07-26 13:30:00+08:00 3 2330 Equity(3 [2330]) 1000 240.842713 \n",
"2018-07-27 13:30:00+08:00 3 2330 Equity(3 [2330]) 500 241.191125 \n",
"2018-07-30 13:30:00+08:00 3 2330 Equity(3 [2330]) 500 241.191125 \n",
"2018-07-31 13:30:00+08:00 3 2330 Equity(3 [2330]) -300 245.065200 \n",
"2018-08-01 13:30:00+08:00 3 2330 Equity(3 [2330]) -300 245.065200 \n",
"\n",
" last_sale_price \n",
"2018-07-25 13:30:00+08:00 240.5 \n",
"2018-07-26 13:30:00+08:00 241.0 \n",
"2018-07-27 13:30:00+08:00 244.5 \n",
"2018-07-30 13:30:00+08:00 245.5 \n",
"2018-07-31 13:30:00+08:00 246.0 \n",
"2018-08-01 13:30:00+08:00 248.0 "
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# 7/31持有股數(amount)變成-300\n",
"positions[0:6]"
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "7f73f7d3",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"2018-07-24 13:30:00+08:00 0\n",
"2018-07-25 13:30:00+08:00 0\n",
"2018-07-26 13:30:00+08:00 0\n",
"2018-07-27 13:30:00+08:00 0\n",
"2018-07-30 13:30:00+08:00 0\n",
"2018-07-31 13:30:00+08:00 1\n",
"2018-08-01 13:30:00+08:00 1\n",
"2018-08-02 13:30:00+08:00 1\n",
"2018-08-03 13:30:00+08:00 1\n",
"2018-08-06 13:30:00+08:00 1\n",
"2018-08-07 13:30:00+08:00 1\n",
"2018-08-08 13:30:00+08:00 1\n",
"2018-08-09 13:30:00+08:00 1\n",
"2018-08-10 13:30:00+08:00 1\n",
"2018-08-13 13:30:00+08:00 1\n",
"2018-08-14 13:30:00+08:00 1\n",
"2018-08-15 13:30:00+08:00 1\n",
"2018-08-16 13:30:00+08:00 1\n",
"2018-08-17 13:30:00+08:00 1\n",
"2018-08-20 13:30:00+08:00 1\n",
"2018-08-21 13:30:00+08:00 1\n",
"2018-08-22 13:30:00+08:00 1\n",
"2018-08-23 13:30:00+08:00 1\n",
"2018-08-24 13:30:00+08:00 1\n",
"Name: shorts_count, dtype: int64"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# 持有short_position的股票個數\n",
"performance.shorts_count"
]
},
{
"cell_type": "markdown",
"id": "562db2fc",
"metadata": {},
"source": [
"\n",
"# set_max_leverage\n",
"設定投資組合的槓桿限制\n",
"\n",
"[Return to Menu](#menu)\n",
"\n",
"### zipline.api.set_max_leverage(max_leverage)\n",
"\n",
"max_leverage (*float*) \n",
"- 投資組合的最高槓桿,必須 > 0。\n",
"- 這邊的槓桿指的是`gross leverage`。\n",
" - 計算方式:`(long_exposure - short_exposure)/(long_exposure + short_exposure + ending_cash)`。\n",
" - ending_cash:當日結束時帳上持有現金。計算方式:starting_cash - capital_used。\n",
" - long_exposure:sum ( 持有股數 * 收盤價 ) = sum ( amount * last_sale_price ),where amount > 0。\n",
" - short_exposure:sum ( 持有股數 * 收盤價 ) = sum ( amount * last_sale_price ),where amount < 0。所以short_exposure <= 0。\n",
" - 參考連結:[lecture/TSMC buy and hold strategy.ipynb](https://github.com/tejtw/TQuant-Lab/blob/main/lecture/TSMC%20buy%20and%20hold%20strategy.ipynb)\n",
"\n",
" \n",
"\n",
"#### 補充說明\n",
"- 當投資組合的槓桿**超過**`max_leverage`時,程式會 **fail**。\n",
"- 無法選擇以'log'方式呈現。\n",
"\n",
"#### 範例\n",
"- 在以下這個範例,我們設定`set_max_leverage(3.0)`。\n",
"- 在7/24先 long 價值一百萬的 2330 股票,short 價值一百萬的 2317 股票。\n",
"```python\n",
"def handle_data(context, data):\n",
" if context.i == 0: # 7/24\n",
" order_value(symbol('2330'), 1e6)\n",
" order_value(symbol('2317'), -1e6)\n",
" ...\n",
"```\n",
"- 在7/26 long 價值五十萬的 2454 股票。\n",
"```python\n",
"if context.i == 2: # 7/26\n",
" order_value(symbol('2454'), 5e5)\n",
"```"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "a06c0e8b",
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"[2023-09-25 08:25:18.380745]: INFO: handle_simulation_end: Simulated 24 trading days\n",
"first open: 2018-07-24 01:01:00+00:00\n",
"last close: 2018-08-24 05:30:00+00:00\n"
]
}
],
"source": [
"def initialize(context):\n",
" context.i = 0\n",
" set_slippage(slippage.FixedSlippage(spread = 0.0))\n",
" set_max_leverage(3.0)\n",
" set_commission(commission.PerDollar(cost=commission_cost))\n",
" set_benchmark(symbol('IR0001'))\n",
" \n",
"def handle_data(context, data):\n",
" \n",
" if context.i == 0: # 7/24\n",
" order_value(symbol('2330'), 1e6)\n",
" order_value(symbol('2317'), -1e6)\n",
" \n",
" if context.i == 2: # 7/26\n",
" order_value(symbol('2454'), 5e5)\n",
"\n",
" context.i += 1\n",
" \n",
"commission_cost = 0.001425\n",
"capital_base = 1e6\n",
"\n",
"\n",
"performance = run_algorithm(start=start_dt,\n",
" end=end_dt,\n",
" initialize=initialize,\n",
" handle_data=handle_data,\n",
" capital_base=capital_base,\n",
" trading_calendar=get_calendar(calendar_name),\n",
" bundle=bundle_name)\n",
"\n",
"positions, transactions, orders = get_transaction_detail(performance)"
]
},
{
"cell_type": "markdown",
"id": "68c382fb",
"metadata": {},
"source": [
"`gross_leverage` 可以直接從`run_algorithm`的結果進行觀察。(`performance['gross_leverage']`)\n",
"- 計算方式如下,以7/25為例:\n",
"\n",
"```\n",
"leverage\n",
"= ( long_exposure - short_exposure ) / ( long_exposure + short_exposure + ending_cash )\n",
"= ( 2330 的 amount * 2330 的 last_sale_price - 2317 的 amount * 2317 的 last_sale_price ) / \n",
" ( ending_cash + 2330 的 amount * 2330 的 last_sale_price + 2317 的 amount * 2317 的 last_sale_price )\n",
"= ( 4149 * 240.5 - (- 11737 ) * 82.7 ) / ( 970010.30973 + 4149 * 240.5 + (- 11737 ) * 82.7 )\n",
"= 1.974022\n",
"```\n",
"\n",
"#### 範例說明:\n",
" - `last_sale_price`及`amount`皆來自`performance`中的`positions`。\n",
" - `last_sale_price`代表標的最近一筆的收盤價。\n",
" - `amount`代表該標的總持有股數。\n",
" - `ending_cash`來自`performance`中的`ending_cash`,代表當日結束時帳上持有現金。\n",
" - 以上欄位定義的參考連結:[lecture/TSMC buy and hold strategy.ipynb](https://github.com/tejtw/TQuant-Lab/blob/main/lecture/TSMC%20buy%20and%20hold%20strategy.ipynb)"
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "9a10d35a",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
" \n",
" \n",
" \n",
" | \n",
" gross_leverage | \n",
" portfolio_value | \n",
" ending_cash | \n",
" \n",
" \n",
" \n",
" \n",
" 2018-07-25 13:30:00+08:00 | \n",
" 1.974022 | \n",
" 9.971949e+05 | \n",
" 970010.309730 | \n",
" \n",
" \n",
" 2018-07-26 13:30:00+08:00 | \n",
" 2.000191 | \n",
" 9.898798e+05 | \n",
" 970010.309730 | \n",
" \n",
" \n",
" 2018-07-27 13:30:00+08:00 | \n",
" 2.481604 | \n",
" 1.007198e+06 | \n",
" 460768.172293 | \n",
" \n",
" \n",
" \n",
" "
],
"text/plain": [
" gross_leverage portfolio_value ending_cash\n",
"2018-07-25 13:30:00+08:00 1.974022 9.971949e+05 970010.309730\n",
"2018-07-26 13:30:00+08:00 2.000191 9.898798e+05 970010.309730\n",
"2018-07-27 13:30:00+08:00 2.481604 1.007198e+06 460768.172293"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"performance.loc['2018-07-25':'2018-07-27',['gross_leverage','portfolio_value','ending_cash']]"
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "9bb1d643",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
" \n",
" \n",
" \n",
" | \n",
" sid | \n",
" symbol | \n",
" asset | \n",
" amount | \n",
" cost_basis | \n",
" last_sale_price | \n",
" \n",
" \n",
" \n",
" \n",
" 2018-07-25 13:30:00+08:00 | \n",
" 3 | \n",
" 2330 | \n",
" Equity(3 [2330]) | \n",
" 4149 | \n",
" 240.842712 | \n",
" 240.5 | \n",
" \n",
" \n",
" 2018-07-25 13:30:00+08:00 | \n",
" 2 | \n",
" 2317 | \n",
" Equity(2 [2317]) | \n",
" -11737 | \n",
" 82.582153 | \n",
" 82.7 | \n",
" \n",
" \n",
" \n",
" "
],
"text/plain": [
" sid symbol asset amount cost_basis \\\n",
"2018-07-25 13:30:00+08:00 3 2330 Equity(3 [2330]) 4149 240.842712 \n",
"2018-07-25 13:30:00+08:00 2 2317 Equity(2 [2317]) -11737 82.582153 \n",
"\n",
" last_sale_price \n",
"2018-07-25 13:30:00+08:00 240.5 \n",
"2018-07-25 13:30:00+08:00 82.7 "
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"positions[0:2]"
]
},
{
"cell_type": "markdown",
"id": "20587b67",
"metadata": {},
"source": [
"- 假設我們設定`set_max_leverage(2.0)`,在7/26時因為股價波動,leverage 超過 2.0,程式就會被終止,跳出錯誤訊息。\n",
"- 那如果`set_max_leverage(2.4)`,且在7/27 long價值 50 萬的 2454,leverage 會達到 2.48,程式也一樣會被終止,跳出錯誤訊息。"
]
},
{
"cell_type": "markdown",
"id": "1cb09ccf",
"metadata": {},
"source": [
"\n",
"# set_max_order_count\n",
"限制一天內能夠下幾張 order\n",
"\n",
"[Return to Menu](#menu)\n",
"\n",
"### zipline.api.set_max_order_count(max_count, on_error='fail')\n",
"- max_count (*int*):一天內最多的下單數。\n",
" \n",
"- on_error (*str, optional*):\n",
" - on_error有兩種選項:'fail' 和 'log'。前者直接中斷程式並顯示錯誤訊息,後者會照樣執行但記錄錯誤。預設為'fail'。\n",
" - 若要使用on_error = 'log',請同時進行以下設定,才能顯示 log:\n",
"\n",
" ```python\n",
" from logbook import Logger, StderrHandler, INFO\n",
" # 設定log顯示方式\n",
" log_handler = StderrHandler(format_string='[{record.time:%Y-%m-%d %H:%M:%S.%f}]: ' +\n",
" '{record.level_name}: {record.func_name}: {record.message}',\n",
" level=INFO)\n",
" log_handler.push_application()\n",
" log = Logger('Algorithm')\n",
" ```\n",
" \n",
"#### 範例\n",
"- 在以下範例中,我們設定`set_max_order_count(max_count=3, on_error='log')`,限制最大下單數為 3。\n",
"- 設定滑價模型:`set_slippage(slippage.VolumeShareSlippage(volume_limit=0.025, price_impact=0.1))`,成交量限制為 2.5%。\n",
"- 下單:\n",
" - 7/24 long 2330 及 2357 兩檔股票。\n",
" - 7/25 long 2454、2317 及 1101 三檔股票。\n",
"\n",
"```python\n",
"def handle_data(context, data):\n",
" if context.i == 0: # 7/24\n",
" order_value(symbol('2330'), 5e8)\n",
" order_value(symbol('2357'), 3e8)\n",
"\n",
" if context.i == 1: # 7/25\n",
" order_value(symbol('2454'), 5e5)\n",
" order_value(symbol('2317'), 5e5)\n",
" order_value(symbol('1101'), 5e5)\n",
" ...\n",
"```\n",
"\n",
"#### 補充說明\n",
"- 訂單數的計算方式:若要計算2018/7/25的訂單數,則從`performance`的`orders`取出`created = '2018-07-25'`的訂單進行計算。\n",
"- 也就是說,如果因**滑價**或**條件單**的關係,訂單被拆成好幾天成交,則該張訂單只有在**成立那天**才會納入計算。\n",
"\n",
"[Return to Menu](#menu)"
]
},
{
"cell_type": "code",
"execution_count": 13,
"id": "c89f669e",
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"[2023-09-25 08:25:21.394726]: INFO: handle_simulation_end: Simulated 24 trading days\n",
"first open: 2018-07-24 01:01:00+00:00\n",
"last close: 2018-08-24 05:30:00+00:00\n"
]
}
],
"source": [
"def initialize(context):\n",
" context.i = 0\n",
" set_slippage(slippage.VolumeShareSlippage(volume_limit=0.025, price_impact=0.1))\n",
" set_max_order_count(max_count=3, on_error='log')\n",
" set_commission(commission.PerDollar(cost=commission_cost))\n",
" set_benchmark(symbol('IR0001'))\n",
" \n",
"def handle_data(context, data):\n",
" \n",
" if context.i == 0: # 7/24\n",
" order_value(symbol('2330'), 5e8)\n",
" order_value(symbol('2357'), 3e8)\n",
" \n",
" if context.i == 1: # 7/25\n",
" order_value(symbol('2454'), 5e5)\n",
" order_value(symbol('2317'), 5e5)\n",
" order_value(symbol('1101'), 5e5)\n",
"\n",
" context.i += 1\n",
" \n",
"\n",
"commission_cost = 0.001425\n",
"capital_base = 1e9\n",
"\n",
"performance = run_algorithm(start=start_dt,\n",
" end=end_dt,\n",
" initialize=initialize,\n",
" handle_data=handle_data,\n",
" capital_base=capital_base,\n",
" trading_calendar=get_calendar(calendar_name),\n",
" bundle=bundle_name)\n",
"\n",
"positions, transactions, orders = get_transaction_detail(performance)"
]
},
{
"cell_type": "markdown",
"id": "cd81fe5b",
"metadata": {},
"source": [
"#### 範例說明\n",
"- 在7/24下單大量的 2330 和 2357,因為`VolumeShareSlippage`的限制,所以會拆成數天成交。\n",
"- 這個會導致7/25不只有當天下的三張訂單,還有前一天 2330 和 2357 的單,共五張單。\n",
"- 但是程式沒有跳出任何錯誤或警告,因為第一天下兩張單,第二天下三張單,程式判定都沒有超過 3,所以沒有問題。"
]
},
{
"cell_type": "code",
"execution_count": 14,
"id": "7c25b10f",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
" \n",
" \n",
" \n",
" | \n",
" sid | \n",
" symbol | \n",
" id | \n",
" dt | \n",
" reason | \n",
" created | \n",
" amount | \n",
" filled | \n",
" commission | \n",
" stop | \n",
" limit | \n",
" stop_reached | \n",
" limit_reached | \n",
" asset | \n",
" status | \n",
" \n",
" \n",
" \n",
" \n",
" 2018-07-25 13:30:00+08:00 | \n",
" 3 | \n",
" 2330 | \n",
" 2f3d2c75c6a14f0982e20325263d801e | \n",
" 2018-07-25 13:30:00+08:00 | \n",
" None | \n",
" 2018-07-24 13:30:00+08:00 | \n",
" 2074688 | \n",
" 538250 | \n",
" 184476.532188 | \n",
" None | \n",
" None | \n",
" False | \n",
" False | \n",
" Equity(3 [2330]) | \n",
" 0 | \n",
" \n",
" \n",
" 2018-07-25 13:30:00+08:00 | \n",
" 4 | \n",
" 2357 | \n",
" 0c8c942572bb4ca9a8ce29ad629133c4 | \n",
" 2018-07-25 13:30:00+08:00 | \n",
" None | \n",
" 2018-07-24 13:30:00+08:00 | \n",
" 1138519 | \n",
" 53175 | \n",
" 19778.347944 | \n",
" None | \n",
" None | \n",
" False | \n",
" False | \n",
" Equity(4 [2357]) | \n",
" 0 | \n",
" \n",
" \n",
" 2018-07-25 13:30:00+08:00 | \n",
" 5 | \n",
" 2454 | \n",
" e69b7d9d8b164b4d9939038ca0c855a0 | \n",
" 2018-07-25 13:30:00+08:00 | \n",
" None | \n",
" 2018-07-25 13:30:00+08:00 | \n",
" 1904 | \n",
" 0 | \n",
" 0.000000 | \n",
" None | \n",
" None | \n",
" False | \n",
" False | \n",
" Equity(5 [2454]) | \n",
" 0 | \n",
" \n",
" \n",
" 2018-07-25 13:30:00+08:00 | \n",
" 2 | \n",
" 2317 | \n",
" 8ba7f1517291473b8bf6649451c2c63f | \n",
" 2018-07-25 13:30:00+08:00 | \n",
" None | \n",
" 2018-07-25 13:30:00+08:00 | \n",
" 6045 | \n",
" 0 | \n",
" 0.000000 | \n",
" None | \n",
" None | \n",
" False | \n",
" False | \n",
" Equity(2 [2317]) | \n",
" 0 | \n",
" \n",
" \n",
" 2018-07-25 13:30:00+08:00 | \n",
" 0 | \n",
" 1101 | \n",
" 62895a53e99b4f5d96a2f178705220fd | \n",
" 2018-07-25 13:30:00+08:00 | \n",
" None | \n",
" 2018-07-25 13:30:00+08:00 | \n",
" 11086 | \n",
" 0 | \n",
" 0.000000 | \n",
" None | \n",
" None | \n",
" False | \n",
" False | \n",
" Equity(0 [1101]) | \n",
" 0 | \n",
" \n",
" \n",
" \n",
" "
],
"text/plain": [
" sid symbol id \\\n",
"2018-07-25 13:30:00+08:00 3 2330 2f3d2c75c6a14f0982e20325263d801e \n",
"2018-07-25 13:30:00+08:00 4 2357 0c8c942572bb4ca9a8ce29ad629133c4 \n",
"2018-07-25 13:30:00+08:00 5 2454 e69b7d9d8b164b4d9939038ca0c855a0 \n",
"2018-07-25 13:30:00+08:00 2 2317 8ba7f1517291473b8bf6649451c2c63f \n",
"2018-07-25 13:30:00+08:00 0 1101 62895a53e99b4f5d96a2f178705220fd \n",
"\n",
" dt reason \\\n",
"2018-07-25 13:30:00+08:00 2018-07-25 13:30:00+08:00 None \n",
"2018-07-25 13:30:00+08:00 2018-07-25 13:30:00+08:00 None \n",
"2018-07-25 13:30:00+08:00 2018-07-25 13:30:00+08:00 None \n",
"2018-07-25 13:30:00+08:00 2018-07-25 13:30:00+08:00 None \n",
"2018-07-25 13:30:00+08:00 2018-07-25 13:30:00+08:00 None \n",
"\n",
" created amount filled \\\n",
"2018-07-25 13:30:00+08:00 2018-07-24 13:30:00+08:00 2074688 538250 \n",
"2018-07-25 13:30:00+08:00 2018-07-24 13:30:00+08:00 1138519 53175 \n",
"2018-07-25 13:30:00+08:00 2018-07-25 13:30:00+08:00 1904 0 \n",
"2018-07-25 13:30:00+08:00 2018-07-25 13:30:00+08:00 6045 0 \n",
"2018-07-25 13:30:00+08:00 2018-07-25 13:30:00+08:00 11086 0 \n",
"\n",
" commission stop limit stop_reached \\\n",
"2018-07-25 13:30:00+08:00 184476.532188 None None False \n",
"2018-07-25 13:30:00+08:00 19778.347944 None None False \n",
"2018-07-25 13:30:00+08:00 0.000000 None None False \n",
"2018-07-25 13:30:00+08:00 0.000000 None None False \n",
"2018-07-25 13:30:00+08:00 0.000000 None None False \n",
"\n",
" limit_reached asset status \n",
"2018-07-25 13:30:00+08:00 False Equity(3 [2330]) 0 \n",
"2018-07-25 13:30:00+08:00 False Equity(4 [2357]) 0 \n",
"2018-07-25 13:30:00+08:00 False Equity(5 [2454]) 0 \n",
"2018-07-25 13:30:00+08:00 False Equity(2 [2317]) 0 \n",
"2018-07-25 13:30:00+08:00 False Equity(0 [1101]) 0 "
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"orders.loc['2018-07-25']"
]
},
{
"cell_type": "markdown",
"id": "30e21b27",
"metadata": {},
"source": [
"如果設定`set_max_order_count(max_count=2, on_error='log')`,則在7/25會出現以下訊息:\n",
"\n",
"```python\n",
"ERROR: handle_violation: Order for 11086 shares of Equity(0 [1101]) at 2018-07-25 05:30:00+00:00 violates trading constraint MaxOrderCount({'max_count': 2})\n",
"```"
]
},
{
"cell_type": "markdown",
"id": "acbb2c3a",
"metadata": {},
"source": [
"\n",
"# set_max_order_size\n",
"這個函數限制特定股票(或全部)的**單次下單股數和金額**\n",
"\n",
"[Return to Menu](#menu)\n",
"\n",
"### zipline.api.set_max_order_size(asset=None, max_shares=None, max_notional=None, on_error='fail')\n",
"- asset (*Asset, optional*)\n",
" - 必須是`Asset`物件(`zipline.assets.Asset`,例如:Equity(0 [1101]),透過`symbol(\"1101\")`可將 symbol 轉成`Asset`物件)\n",
" - 若**不為 None** 會對**指定股票**進行限制。\n",
" - 若設定為 **None** 則會讓**所有股票**皆適用這個限制條件。\n",
"- max_shares (*int, optional*)-最大單次下單股數。\n",
"- max_notional (*float, optional*)-最大單次下單金額。\n",
"- on_error (*str, optional*):\n",
" - on_error有兩種選項:'fail' 和 'log'。前者直接中斷程式並顯示錯誤訊息,後者會照樣執行但記錄錯誤。預設為'fail'。\n",
" - 若要使用on_error = 'log',請同時進行以下設定,才能顯示log:\n",
"\n",
" ```python\n",
" from logbook import Logger, StderrHandler, INFO\n",
" # 設定log顯示方式\n",
" log_handler = StderrHandler(format_string='[{record.time:%Y-%m-%d %H:%M:%S.%f}]: ' +\n",
" '{record.level_name}: {record.func_name}: {record.message}',\n",
" level=INFO)\n",
" log_handler.push_application()\n",
" log = Logger('Algorithm')\n",
" ```\n",
"\n",
"#### 補充說明:\n",
"- `max_shares` 是以**下單時股數**為準。\n",
"- `max_notional` 計算方法為**下單時的股數 * 下單當天收盤價**,所以成交時的股數和金額可能還是會超過`set_max_order_size`的限制,細節在下面的範例說明。\n",
"\n",
"#### 範例\n",
"- 在以下這個範例,我們限制 1101 的 max_shares = 1000,且限制 2330 的 max_shares = 2000 、max_notional = 481000。\n",
"```python\n",
"def initialize(context):\n",
" ...\n",
" set_max_order_size(asset= symbol('1101'), max_shares=1000, on_error='log')\n",
" set_max_order_size(asset= symbol('2330'), max_shares=2000, max_notional=481000, on_error='log')\n",
" ...\n",
"```\n",
"- 在7/25 long 1000股的 1101 股票及 2000 股的 2330 股票。\n",
"```python\n",
"def handle_data(context, data):\n",
" if context.i == 1: # 2018-07-25\n",
" order(symbol('1101'), 1000)\n",
" order(symbol('2330'), 2000)\n",
" ...\n",
"```\n",
"- 在8/16 long 2005 股的 2330 股票。\n",
"```python\n",
"if context.i == 17: # 2018-08-16\n",
" order(symbol('2330'), 2005)\n",
"```"
]
},
{
"cell_type": "code",
"execution_count": 15,
"id": "cf13eca8",
"metadata": {
"scrolled": true
},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"[2023-09-25 08:25:23.931322]: ERROR: handle_violation: Order for 2005 shares of Equity(3 [2330]) at 2018-08-16 05:30:00+00:00 violates trading constraint MaxOrderSize({'asset': Equity(3 [2330]), 'max_shares': 2000, 'max_notional': 481000})\n",
"[2023-09-25 08:25:23.949157]: INFO: handle_simulation_end: Simulated 24 trading days\n",
"first open: 2018-07-24 01:01:00+00:00\n",
"last close: 2018-08-24 05:30:00+00:00\n"
]
}
],
"source": [
"def initialize(context):\n",
" context.i = 0\n",
" set_max_order_size(asset= symbol('1101'), max_shares=1000, on_error='log')\n",
" set_max_order_size(asset= symbol('2330'), max_shares=2000, max_notional=481000, on_error='log')\n",
" set_slippage(slippage.FixedSlippage(spread = 0.0))\n",
" set_commission(commission.PerDollar(cost=0.01))\n",
" set_benchmark(symbol('IR0001'))\n",
" \n",
"def handle_data(context, data):\n",
"\n",
" if context.i == 1: # 2018-07-25\n",
" order(symbol('1101'), 1000)\n",
" order(symbol('2330'), 2000)\n",
"\n",
" if context.i == 17: # 2018-08-16\n",
" order(symbol('2330'), 2005)\n",
"\n",
" context.i += 1\n",
"\n",
"\n",
"commission_cost = 0.001425\n",
"capital_base = 1e6\n",
"\n",
"\n",
"performance = run_algorithm(start=start_dt,\n",
" end=end_dt,\n",
" initialize=initialize,\n",
" handle_data=handle_data,\n",
" capital_base=capital_base,\n",
" trading_calendar=get_calendar(calendar_name),\n",
" bundle=bundle_name)\n",
"\n",
"closing_price = tejapi.fastget('TWN/APIPRCD',\n",
" coid=['1101','2330'],\n",
" opts={'columns':['mdate','coid','close_d']},\n",
" mdate={'gte':start_dt,'lte':end_dt },\n",
" paginate=True)\n",
"\n",
"positions, transactions, orders = get_transaction_detail(performance)"
]
},
{
"cell_type": "markdown",
"id": "f72d88a8",
"metadata": {},
"source": [
"#### 觀察7/25下的 1101\n",
"- 在7/25下單 1000 股。\n",
"- 但7/26遇到除權事件,調整後實際上買了1100股 > 限制的 1000 股,但是因為下單時是 1000 股,所以沒有問題。"
]
},
{
"cell_type": "code",
"execution_count": 16,
"id": "842b079e",
"metadata": {
"scrolled": true
},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
" \n",
" \n",
" \n",
" | \n",
" sid | \n",
" symbol | \n",
" id | \n",
" dt | \n",
" reason | \n",
" created | \n",
" amount | \n",
" filled | \n",
" commission | \n",
" stop | \n",
" limit | \n",
" stop_reached | \n",
" limit_reached | \n",
" asset | \n",
" status | \n",
" \n",
" \n",
" \n",
" \n",
" 2018-07-25 13:30:00+08:00 | \n",
" 0 | \n",
" 1101 | \n",
" ae91c552e8444d46ba046678ef6d5735 | \n",
" 2018-07-25 13:30:00+08:00 | \n",
" None | \n",
" 2018-07-25 13:30:00+08:00 | \n",
" 1000 | \n",
" 0 | \n",
" 0.0 | \n",
" None | \n",
" None | \n",
" False | \n",
" False | \n",
" Equity(0 [1101]) | \n",
" 0 | \n",
" \n",
" \n",
" 2018-07-26 13:30:00+08:00 | \n",
" 0 | \n",
" 1101 | \n",
" ae91c552e8444d46ba046678ef6d5735 | \n",
" 2018-07-26 13:30:00+08:00 | \n",
" None | \n",
" 2018-07-25 13:30:00+08:00 | \n",
" 1100 | \n",
" 1100 | \n",
" 445.5 | \n",
" None | \n",
" None | \n",
" False | \n",
" False | \n",
" Equity(0 [1101]) | \n",
" 1 | \n",
" \n",
" \n",
" \n",
" "
],
"text/plain": [
" sid symbol id \\\n",
"2018-07-25 13:30:00+08:00 0 1101 ae91c552e8444d46ba046678ef6d5735 \n",
"2018-07-26 13:30:00+08:00 0 1101 ae91c552e8444d46ba046678ef6d5735 \n",
"\n",
" dt reason \\\n",
"2018-07-25 13:30:00+08:00 2018-07-25 13:30:00+08:00 None \n",
"2018-07-26 13:30:00+08:00 2018-07-26 13:30:00+08:00 None \n",
"\n",
" created amount filled \\\n",
"2018-07-25 13:30:00+08:00 2018-07-25 13:30:00+08:00 1000 0 \n",
"2018-07-26 13:30:00+08:00 2018-07-25 13:30:00+08:00 1100 1100 \n",
"\n",
" commission stop limit stop_reached \\\n",
"2018-07-25 13:30:00+08:00 0.0 None None False \n",
"2018-07-26 13:30:00+08:00 445.5 None None False \n",
"\n",
" limit_reached asset status \n",
"2018-07-25 13:30:00+08:00 False Equity(0 [1101]) 0 \n",
"2018-07-26 13:30:00+08:00 False Equity(0 [1101]) 1 "
]
},
"execution_count": 16,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"orders.query('symbol == \"1101\"')"
]
},
{
"cell_type": "markdown",
"id": "34047e97",
"metadata": {},
"source": [
"#### 觀察7/25下的 2330\n",
"- 在7/25下單 2000 股的 2330 ,當下的 notional = 2000 * 240.5(當天收盤)= 481000,符合設定的兩個限制。\n",
"- 7/26成交時是以 241 元成交,當下的 notional = 2000 * 241 = 482000,超出原本設定的 `max_notional`,但並不會跳錯訊息。"
]
},
{
"cell_type": "code",
"execution_count": 17,
"id": "1d9c37ba",
"metadata": {
"scrolled": true
},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
" \n",
" \n",
" \n",
" | \n",
" mdate | \n",
" coid | \n",
" close_d | \n",
" \n",
" \n",
" \n",
" \n",
" 25 | \n",
" 2018-07-25 | \n",
" 2330 | \n",
" 240.5 | \n",
" \n",
" \n",
" 26 | \n",
" 2018-07-26 | \n",
" 2330 | \n",
" 241.0 | \n",
" \n",
" \n",
" \n",
" "
],
"text/plain": [
" mdate coid close_d\n",
"25 2018-07-25 2330 240.5\n",
"26 2018-07-26 2330 241.0"
]
},
"execution_count": 17,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"closing_price.query('(coid == \"2330\") & (mdate in [\"2018-07-25\",\"2018-07-26\"])')"
]
},
{
"cell_type": "code",
"execution_count": 18,
"id": "34fe4dd2",
"metadata": {
"scrolled": false
},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
" \n",
" \n",
" \n",
" | \n",
" sid | \n",
" symbol | \n",
" amount | \n",
" dt | \n",
" price | \n",
" order_id | \n",
" asset | \n",
" commission | \n",
" \n",
" \n",
" \n",
" \n",
" 2018-07-26 13:30:00+08:00 | \n",
" 0 | \n",
" 1101 | \n",
" 1100 | \n",
" 2018-07-26 13:30:00+08:00 | \n",
" 40.5 | \n",
" ae91c552e8444d46ba046678ef6d5735 | \n",
" Equity(0 [1101]) | \n",
" None | \n",
" \n",
" \n",
" 2018-07-26 13:30:00+08:00 | \n",
" 3 | \n",
" 2330 | \n",
" 2000 | \n",
" 2018-07-26 13:30:00+08:00 | \n",
" 241.0 | \n",
" 2c71621d421a4b51838e0bc65f9e949b | \n",
" Equity(3 [2330]) | \n",
" None | \n",
" \n",
" \n",
" \n",
" "
],
"text/plain": [
" sid symbol amount dt \\\n",
"2018-07-26 13:30:00+08:00 0 1101 1100 2018-07-26 13:30:00+08:00 \n",
"2018-07-26 13:30:00+08:00 3 2330 2000 2018-07-26 13:30:00+08:00 \n",
"\n",
" price order_id \\\n",
"2018-07-26 13:30:00+08:00 40.5 ae91c552e8444d46ba046678ef6d5735 \n",
"2018-07-26 13:30:00+08:00 241.0 2c71621d421a4b51838e0bc65f9e949b \n",
"\n",
" asset commission \n",
"2018-07-26 13:30:00+08:00 Equity(0 [1101]) None \n",
"2018-07-26 13:30:00+08:00 Equity(3 [2330]) None "
]
},
"execution_count": 18,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"transactions.loc['2018-07-26']"
]
},
{
"cell_type": "markdown",
"id": "2fda53f1",
"metadata": {},
"source": [
"#### 觀察8/16下的 2330\n",
"在8/16下 2005 股的 2330,雖然當天 notional = 239 * 2005 = 479195 沒有超過預先設定的 481000,但已經超過 2000 股的限制。因為on_error = 'log',程式繼續運作,照樣成交,但是跳出錯誤訊息:\n",
"\n",
"```python \n",
"ERROR: handle_violation: Order for 2005 shares of Equity(14 [2330]) at 2018-08-16 05:30:00+00:00 violates trading \n",
"constraint MaxOrderSize({'asset': Equity(14 [2330]), 'max_shares': 2000, 'max_notional': 481000})\n",
"``` "
]
},
{
"cell_type": "code",
"execution_count": 19,
"id": "33b18e46",
"metadata": {
"scrolled": false
},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
" \n",
" \n",
" \n",
" | \n",
" mdate | \n",
" coid | \n",
" close_d | \n",
" \n",
" \n",
" \n",
" \n",
" 41 | \n",
" 2018-08-16 | \n",
" 2330 | \n",
" 239.0 | \n",
" \n",
" \n",
" 42 | \n",
" 2018-08-17 | \n",
" 2330 | \n",
" 239.5 | \n",
" \n",
" \n",
" \n",
" "
],
"text/plain": [
" mdate coid close_d\n",
"41 2018-08-16 2330 239.0\n",
"42 2018-08-17 2330 239.5"
]
},
"execution_count": 19,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"closing_price.query('(coid == \"2330\") & (mdate in [\"2018-08-16\",\"2018-08-17\"])')"
]
},
{
"cell_type": "code",
"execution_count": 20,
"id": "d98d4d5a",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
" \n",
" \n",
" \n",
" | \n",
" sid | \n",
" symbol | \n",
" amount | \n",
" dt | \n",
" price | \n",
" order_id | \n",
" asset | \n",
" commission | \n",
" \n",
" \n",
" \n",
" \n",
" 2018-08-17 13:30:00+08:00 | \n",
" 3 | \n",
" 2330 | \n",
" 2005 | \n",
" 2018-08-17 13:30:00+08:00 | \n",
" 239.5 | \n",
" 2363ca6eedd441e0ab297fe80d2f5fef | \n",
" Equity(3 [2330]) | \n",
" None | \n",
" \n",
" \n",
" \n",
" "
],
"text/plain": [
" sid symbol amount dt \\\n",
"2018-08-17 13:30:00+08:00 3 2330 2005 2018-08-17 13:30:00+08:00 \n",
"\n",
" price order_id \\\n",
"2018-08-17 13:30:00+08:00 239.5 2363ca6eedd441e0ab297fe80d2f5fef \n",
"\n",
" asset commission \n",
"2018-08-17 13:30:00+08:00 Equity(3 [2330]) None "
]
},
"execution_count": 20,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"transactions.loc['2018-08-17']"
]
},
{
"cell_type": "markdown",
"id": "36a0d70a",
"metadata": {},
"source": [
"\n",
"# set_max_position_size\n",
"限制特定股票(或全部)在帳上的股數及市值\n",
"\n",
"[Return to Menu](#menu)\n",
"\n",
"### zipline.api.set_max_position_size(asset=None, max_shares=None, max_notional=None, on_error='fail')\n",
"- asset (*Asset, optional*)\n",
" - 必須是`Asset`物件(`zipline.assets.Asset`,例如:Equity(0 [1101]))\n",
" - 若**不為 None** 會對**指定股票**進行限制。\n",
" - 若設定為 **None** 則會讓**所有股票**皆適用這個限制條件。\n",
"- max_shares (*int, optional*)-最大**持股**股數。\n",
"- max_notional (*float, optional*)-最大**持股**市值。\n",
"- on_error (*str, optional*):\n",
" - on_error有兩種選項:'fail' 和 'log'。前者直接中斷程式並顯示錯誤訊息,後者會照樣執行但記錄錯誤。預設為'fail'。\n",
" - 若要使用on_error = 'log',請同時進行以下設定,才能顯示log:\n",
"\n",
" ```python\n",
" from logbook import Logger, StderrHandler, INFO\n",
" # 設定log顯示方式\n",
" log_handler = StderrHandler(format_string='[{record.time:%Y-%m-%d %H:%M:%S.%f}]: ' +\n",
" '{record.level_name}: {record.func_name}: {record.message}',\n",
" level=INFO)\n",
" log_handler.push_application()\n",
" log = Logger('Algorithm')\n",
" ```\n",
" \n",
"#### 補充說明\n",
"- 這個函數用法跟`set_max_order_size()`非常類似,差別在於它是限制某支(或全部)股票在**帳上**的股數及市值,而非針對**單筆訂單**。\n",
"- 這函數**只會在下單當下進行檢查**並判斷帳上的部位(position)會不會超過限制,並不是一直追蹤帳上的部位。\n",
"- 若是我們同一檔股票下兩張訂單,則每張訂單將會**個別判定**。\n",
"- 下面用一些比較特殊的例子,同時應用`max_order_size`和`max_position_size`來解釋運作規則。\n",
"\n",
"#### 範例\n",
"- 在範例中,我們做以下限制: \n",
" - 限制 2330 單筆訂單的 max_shares = 2000、max_notional = 481000。\n",
" - 限制 1101 持股部位的 max_shares = 1050。\n",
" - 限制 2330 持股部位的 max_shares = 2000、max_notional = 600000。\n",
" \n",
" ```python\n",
" def initialize(context):\n",
" ...\n",
" set_max_order_size(asset= symbol('2330'), max_shares=2000, max_notional=481000, on_error='log')\n",
" set_max_position_size(asset= symbol('1101'), max_shares=1050, on_error='log')\n",
" set_max_position_size(asset= symbol('2330'), max_shares=2000, max_notional=600000, on_error='log')\n",
" ...\n",
" ```\n",
"- 下單設定:\n",
" - 在7/24 long 1000股的 1101 股票。\n",
" ```python\n",
" def handle_data(context, data):\n",
" if context.i ==0: # 2018-07-24\n",
" order(symbol('1101'), 1000)\n",
" ```\n",
" - 在7/25 下兩張訂單,分別 long 2000 股及 1000 股的 2330 股票。\n",
" ```python\n",
" if context.i == 1: # 2018-07-25\n",
" order(symbol('2330'), 2000)\n",
" order(symbol('2330'), 1000)\n",
" ```\n",
" - 在7/31 long 500股的 2330 股票。\n",
" ```python\n",
" if context.i == 5: # 2018-07-31\n",
" order(symbol('2330'), 500)\n",
" ```"
]
},
{
"cell_type": "code",
"execution_count": 21,
"id": "8a950c45",
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"[2023-09-25 08:25:28.995945]: INFO: earn_dividends: Equity(0 [1101]), cash_dividend amount: 1.5, pay_date: 2018-08-24, div_owed: 1500.0\n",
"[2023-09-25 08:25:28.996945]: INFO: handle_split: after split: asset: Equity(0 [1101]), amount: 1100, cost_basis: 41.4, last_sale_price: 45.1\n",
"[2023-09-25 08:25:28.996945]: INFO: handle_split: returning cash: 7.33\n",
"[2023-09-25 08:25:29.004945]: ERROR: handle_violation: Order for 500 shares of Equity(3 [2330]) at 2018-07-31 05:30:00+00:00 violates trading constraint MaxPositionSize({'asset': Equity(3 [2330]), 'max_shares': 2000, 'max_notional': 600000})\n",
"[2023-09-25 08:25:29.005946]: ERROR: handle_violation: Order for 500 shares of Equity(3 [2330]) at 2018-07-31 05:30:00+00:00 violates trading constraint MaxPositionSize({'asset': Equity(3 [2330]), 'max_shares': 2000, 'max_notional': 600000})\n",
"[2023-09-25 08:25:29.037109]: INFO: handle_simulation_end: Simulated 24 trading days\n",
"first open: 2018-07-24 01:01:00+00:00\n",
"last close: 2018-08-24 05:30:00+00:00\n"
]
}
],
"source": [
"def initialize(context):\n",
" context.i = 0\n",
" \n",
" set_max_order_size(asset= symbol('2330'), max_shares=2000, max_notional=481000, on_error='log')\n",
" set_max_position_size(asset= symbol('1101'), max_shares=1050, on_error='log')\n",
" set_max_position_size(asset= symbol('2330'), max_shares=2000, max_notional=600000, on_error='log')\n",
" \n",
" set_slippage(slippage.FixedSlippage(spread = 0.0))\n",
" set_commission(commission.PerDollar(cost=0.01))\n",
" set_benchmark(symbol('IR0001'))\n",
" \n",
"def handle_data(context, data):\n",
"\n",
" if context.i ==0: # 2018-07-24\n",
" order(symbol('1101'), 1000)\n",
" \n",
" if context.i == 1: # 2018-07-25\n",
" order(symbol('2330'), 2000)\n",
" order(symbol('2330'), 1000)\n",
"\n",
" if context.i == 5: # 2018-07-31\n",
" order(symbol('2330'), 500)\n",
" \n",
" context.i += 1\n",
"\n",
"\n",
"commission_cost = 0.001425\n",
"capital_base = 1e6\n",
"\n",
"performance = run_algorithm(start=start_dt,\n",
" end=end_dt,\n",
" initialize=initialize,\n",
" handle_data=handle_data,\n",
" capital_base=capital_base,\n",
" trading_calendar=get_calendar(calendar_name),\n",
" bundle=bundle_name)\n",
"\n",
"closing_price = tejapi.fastget('TWN/APIPRCD',\n",
" coid=['1101','2330'],\n",
" opts={'columns':['mdate','coid','close_d']},\n",
" mdate={'gte':start_dt,'lte':end_dt },\n",
" paginate=True)\n",
"\n",
"positions, transactions, orders = get_transaction_detail(performance)"
]
},
{
"cell_type": "markdown",
"id": "94bd193c",
"metadata": {},
"source": [
"#### 觀察7/24下的訂單\n",
"- 雖然7/24下的 1000 股 1101 在7/26除權之後變成 1100 股,超過限制的 1050 股,但沒有錯誤訊息(`MaxPositionSize`)。\n",
"- 此外**因為在下單時,系統判定買 1000 股會讓手上 position 從 0 變成 1000 股,沒有超過 1050**,所以沒有錯誤訊息。\n",
"- 同樣道理,如果單子因為除權事件造成成交股數和下單時股數不同,還是以**下單時股數**為主。"
]
},
{
"cell_type": "code",
"execution_count": 22,
"id": "1c3eaa13",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
" \n",
" \n",
" \n",
" | \n",
" sid | \n",
" symbol | \n",
" id | \n",
" dt | \n",
" reason | \n",
" created | \n",
" amount | \n",
" filled | \n",
" commission | \n",
" stop | \n",
" limit | \n",
" stop_reached | \n",
" limit_reached | \n",
" asset | \n",
" status | \n",
" \n",
" \n",
" \n",
" \n",
" 2018-07-24 13:30:00+08:00 | \n",
" 0 | \n",
" 1101 | \n",
" e6212ce9c29b467d9d4372a7f9ec8bb2 | \n",
" 2018-07-24 13:30:00+08:00 | \n",
" None | \n",
" 2018-07-24 13:30:00+08:00 | \n",
" 1000 | \n",
" 0 | \n",
" 0.0 | \n",
" None | \n",
" None | \n",
" False | \n",
" False | \n",
" Equity(0 [1101]) | \n",
" 0 | \n",
" \n",
" \n",
" 2018-07-25 13:30:00+08:00 | \n",
" 0 | \n",
" 1101 | \n",
" e6212ce9c29b467d9d4372a7f9ec8bb2 | \n",
" 2018-07-25 13:30:00+08:00 | \n",
" None | \n",
" 2018-07-24 13:30:00+08:00 | \n",
" 1000 | \n",
" 1000 | \n",
" 451.0 | \n",
" None | \n",
" None | \n",
" False | \n",
" False | \n",
" Equity(0 [1101]) | \n",
" 1 | \n",
" \n",
" \n",
" \n",
" "
],
"text/plain": [
" sid symbol id \\\n",
"2018-07-24 13:30:00+08:00 0 1101 e6212ce9c29b467d9d4372a7f9ec8bb2 \n",
"2018-07-25 13:30:00+08:00 0 1101 e6212ce9c29b467d9d4372a7f9ec8bb2 \n",
"\n",
" dt reason \\\n",
"2018-07-24 13:30:00+08:00 2018-07-24 13:30:00+08:00 None \n",
"2018-07-25 13:30:00+08:00 2018-07-25 13:30:00+08:00 None \n",
"\n",
" created amount filled \\\n",
"2018-07-24 13:30:00+08:00 2018-07-24 13:30:00+08:00 1000 0 \n",
"2018-07-25 13:30:00+08:00 2018-07-24 13:30:00+08:00 1000 1000 \n",
"\n",
" commission stop limit stop_reached \\\n",
"2018-07-24 13:30:00+08:00 0.0 None None False \n",
"2018-07-25 13:30:00+08:00 451.0 None None False \n",
"\n",
" limit_reached asset status \n",
"2018-07-24 13:30:00+08:00 False Equity(0 [1101]) 0 \n",
"2018-07-25 13:30:00+08:00 False Equity(0 [1101]) 1 "
]
},
"execution_count": 22,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"orders[0:2]"
]
},
{
"cell_type": "code",
"execution_count": 23,
"id": "c49ecff5",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
" \n",
" \n",
" \n",
" | \n",
" sid | \n",
" symbol | \n",
" asset | \n",
" amount | \n",
" cost_basis | \n",
" last_sale_price | \n",
" \n",
" \n",
" \n",
" \n",
" 2018-07-25 13:30:00+08:00 | \n",
" 0 | \n",
" 1101 | \n",
" Equity(0 [1101]) | \n",
" 1000 | \n",
" 45.551 | \n",
" 45.1 | \n",
" \n",
" \n",
" 2018-07-26 13:30:00+08:00 | \n",
" 0 | \n",
" 1101 | \n",
" Equity(0 [1101]) | \n",
" 1100 | \n",
" 41.400 | \n",
" 40.5 | \n",
" \n",
" \n",
" \n",
" "
],
"text/plain": [
" sid symbol asset amount cost_basis \\\n",
"2018-07-25 13:30:00+08:00 0 1101 Equity(0 [1101]) 1000 45.551 \n",
"2018-07-26 13:30:00+08:00 0 1101 Equity(0 [1101]) 1100 41.400 \n",
"\n",
" last_sale_price \n",
"2018-07-25 13:30:00+08:00 45.1 \n",
"2018-07-26 13:30:00+08:00 40.5 "
]
},
"execution_count": 23,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"positions[0:2]"
]
},
{
"cell_type": "markdown",
"id": "7944ce84",
"metadata": {},
"source": [
"#### 觀察7/25下的訂單\n",
"- 在7/25連續下了兩單,分別是 2000 股和 1000 股的 2330,雖然總和是 3000 股,超過限制的 2000 股,但也沒有錯誤訊息(`MaxOrderSize`)。**因為兩單都沒有超過max_order_size 的 2000 股限制**。\n",
"- 而因為這兩張單子隔天(7/26)才會成交,下單時 position = 0,`max_position_size`認為其中一單是讓 position 從 0 變成 2000,另一單是讓 position 從 0 變成 1000,都沒有超過總股數 2000 的限制(`max_notional`部分也是同樣概念),所以也沒有錯誤訊息(`MaxPositionSize`)。\n",
"- 接下來幾天股價上升,notional也早就超過`max_notional(600000)`,但也沒有錯誤訊息,因為並不是一直追蹤帳上的部位。"
]
},
{
"cell_type": "markdown",
"id": "731a833d",
"metadata": {},
"source": [
"#### 觀察7/31下的訂單\n",
"- 7/31下單 500 股 2330 時跳出以下錯誤訊息,因為帳上 3000 股,再加 500,就會超過2000(`max_notional`部分也是同樣概念)。\n",
"- 而且因為**超過了兩個限制**,同一筆交易跳出**兩行**錯誤訊息(但因為我們用on_error = 'log',所有訂單還是成交)。\n",
"\n",
"```python\n",
"ERROR: handle_violation: Order for 500 shares of Equity(3 [2330]) at 2018-07-31 05:30:00+00:00 violates trading constraint MaxPositionSize({'asset': Equity(3 [2330]), 'max_shares': 2000, 'max_notional': 600000})\n",
"\n",
"ERROR: handle_violation: Order for 500 shares of Equity(3 [2330]) at 2018-07-31 05:30:00+00:00 violates trading constraint MaxPositionSize({'asset': Equity(3 [2330]), 'max_shares': 2000, 'max_notional': 600000})\n",
"```"
]
},
{
"cell_type": "code",
"execution_count": 24,
"id": "e3c81be9",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
" \n",
" \n",
" \n",
" | \n",
" sid | \n",
" symbol | \n",
" id | \n",
" dt | \n",
" reason | \n",
" created | \n",
" amount | \n",
" filled | \n",
" commission | \n",
" stop | \n",
" limit | \n",
" stop_reached | \n",
" limit_reached | \n",
" asset | \n",
" status | \n",
" \n",
" \n",
" \n",
" \n",
" 2018-07-25 13:30:00+08:00 | \n",
" 3 | \n",
" 2330 | \n",
" b04afe6c14f440c4bbc460cdb6fea2fd | \n",
" 2018-07-25 13:30:00+08:00 | \n",
" None | \n",
" 2018-07-25 13:30:00+08:00 | \n",
" 2000 | \n",
" 0 | \n",
" 0.0 | \n",
" None | \n",
" None | \n",
" False | \n",
" False | \n",
" Equity(3 [2330]) | \n",
" 0 | \n",
" \n",
" \n",
" 2018-07-25 13:30:00+08:00 | \n",
" 3 | \n",
" 2330 | \n",
" 1097aa119bbc4f2ebe42eb627c02ed0f | \n",
" 2018-07-25 13:30:00+08:00 | \n",
" None | \n",
" 2018-07-25 13:30:00+08:00 | \n",
" 1000 | \n",
" 0 | \n",
" 0.0 | \n",
" None | \n",
" None | \n",
" False | \n",
" False | \n",
" Equity(3 [2330]) | \n",
" 0 | \n",
" \n",
" \n",
" 2018-07-26 13:30:00+08:00 | \n",
" 3 | \n",
" 2330 | \n",
" b04afe6c14f440c4bbc460cdb6fea2fd | \n",
" 2018-07-26 13:30:00+08:00 | \n",
" None | \n",
" 2018-07-25 13:30:00+08:00 | \n",
" 2000 | \n",
" 2000 | \n",
" 4820.0 | \n",
" None | \n",
" None | \n",
" False | \n",
" False | \n",
" Equity(3 [2330]) | \n",
" 1 | \n",
" \n",
" \n",
" 2018-07-26 13:30:00+08:00 | \n",
" 3 | \n",
" 2330 | \n",
" 1097aa119bbc4f2ebe42eb627c02ed0f | \n",
" 2018-07-26 13:30:00+08:00 | \n",
" None | \n",
" 2018-07-25 13:30:00+08:00 | \n",
" 1000 | \n",
" 1000 | \n",
" 2410.0 | \n",
" None | \n",
" None | \n",
" False | \n",
" False | \n",
" Equity(3 [2330]) | \n",
" 1 | \n",
" \n",
" \n",
" 2018-07-31 13:30:00+08:00 | \n",
" 3 | \n",
" 2330 | \n",
" 7eaa433315ec438b9837695951a0b126 | \n",
" 2018-07-31 13:30:00+08:00 | \n",
" None | \n",
" 2018-07-31 13:30:00+08:00 | \n",
" 500 | \n",
" 0 | \n",
" 0.0 | \n",
" None | \n",
" None | \n",
" False | \n",
" False | \n",
" Equity(3 [2330]) | \n",
" 0 | \n",
" \n",
" \n",
" 2018-08-01 13:30:00+08:00 | \n",
" 3 | \n",
" 2330 | \n",
" 7eaa433315ec438b9837695951a0b126 | \n",
" 2018-08-01 13:30:00+08:00 | \n",
" None | \n",
" 2018-07-31 13:30:00+08:00 | \n",
" 500 | \n",
" 500 | \n",
" 1240.0 | \n",
" None | \n",
" None | \n",
" False | \n",
" False | \n",
" Equity(3 [2330]) | \n",
" 1 | \n",
" \n",
" \n",
" \n",
" "
],
"text/plain": [
" sid symbol id \\\n",
"2018-07-25 13:30:00+08:00 3 2330 b04afe6c14f440c4bbc460cdb6fea2fd \n",
"2018-07-25 13:30:00+08:00 3 2330 1097aa119bbc4f2ebe42eb627c02ed0f \n",
"2018-07-26 13:30:00+08:00 3 2330 b04afe6c14f440c4bbc460cdb6fea2fd \n",
"2018-07-26 13:30:00+08:00 3 2330 1097aa119bbc4f2ebe42eb627c02ed0f \n",
"2018-07-31 13:30:00+08:00 3 2330 7eaa433315ec438b9837695951a0b126 \n",
"2018-08-01 13:30:00+08:00 3 2330 7eaa433315ec438b9837695951a0b126 \n",
"\n",
" dt reason \\\n",
"2018-07-25 13:30:00+08:00 2018-07-25 13:30:00+08:00 None \n",
"2018-07-25 13:30:00+08:00 2018-07-25 13:30:00+08:00 None \n",
"2018-07-26 13:30:00+08:00 2018-07-26 13:30:00+08:00 None \n",
"2018-07-26 13:30:00+08:00 2018-07-26 13:30:00+08:00 None \n",
"2018-07-31 13:30:00+08:00 2018-07-31 13:30:00+08:00 None \n",
"2018-08-01 13:30:00+08:00 2018-08-01 13:30:00+08:00 None \n",
"\n",
" created amount filled \\\n",
"2018-07-25 13:30:00+08:00 2018-07-25 13:30:00+08:00 2000 0 \n",
"2018-07-25 13:30:00+08:00 2018-07-25 13:30:00+08:00 1000 0 \n",
"2018-07-26 13:30:00+08:00 2018-07-25 13:30:00+08:00 2000 2000 \n",
"2018-07-26 13:30:00+08:00 2018-07-25 13:30:00+08:00 1000 1000 \n",
"2018-07-31 13:30:00+08:00 2018-07-31 13:30:00+08:00 500 0 \n",
"2018-08-01 13:30:00+08:00 2018-07-31 13:30:00+08:00 500 500 \n",
"\n",
" commission stop limit stop_reached \\\n",
"2018-07-25 13:30:00+08:00 0.0 None None False \n",
"2018-07-25 13:30:00+08:00 0.0 None None False \n",
"2018-07-26 13:30:00+08:00 4820.0 None None False \n",
"2018-07-26 13:30:00+08:00 2410.0 None None False \n",
"2018-07-31 13:30:00+08:00 0.0 None None False \n",
"2018-08-01 13:30:00+08:00 1240.0 None None False \n",
"\n",
" limit_reached asset status \n",
"2018-07-25 13:30:00+08:00 False Equity(3 [2330]) 0 \n",
"2018-07-25 13:30:00+08:00 False Equity(3 [2330]) 0 \n",
"2018-07-26 13:30:00+08:00 False Equity(3 [2330]) 1 \n",
"2018-07-26 13:30:00+08:00 False Equity(3 [2330]) 1 \n",
"2018-07-31 13:30:00+08:00 False Equity(3 [2330]) 0 \n",
"2018-08-01 13:30:00+08:00 False Equity(3 [2330]) 1 "
]
},
"execution_count": 24,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"orders.query('symbol==\"2330\"')"
]
},
{
"cell_type": "code",
"execution_count": 25,
"id": "f8a5dd3a",
"metadata": {
"scrolled": true
},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
" \n",
" \n",
" \n",
" | \n",
" sid | \n",
" symbol | \n",
" asset | \n",
" amount | \n",
" cost_basis | \n",
" last_sale_price | \n",
" mv | \n",
" \n",
" \n",
" \n",
" \n",
" 2018-07-26 13:30:00+08:00 | \n",
" 3 | \n",
" 2330 | \n",
" Equity(3 [2330]) | \n",
" 3000 | \n",
" 243.41 | \n",
" 241.0 | \n",
" 723000.0 | \n",
" \n",
" \n",
" 2018-07-27 13:30:00+08:00 | \n",
" 3 | \n",
" 2330 | \n",
" Equity(3 [2330]) | \n",
" 3000 | \n",
" 243.41 | \n",
" 244.5 | \n",
" 733500.0 | \n",
" \n",
" \n",
" 2018-07-30 13:30:00+08:00 | \n",
" 3 | \n",
" 2330 | \n",
" Equity(3 [2330]) | \n",
" 3000 | \n",
" 243.41 | \n",
" 245.5 | \n",
" 736500.0 | \n",
" \n",
" \n",
" 2018-07-31 13:30:00+08:00 | \n",
" 3 | \n",
" 2330 | \n",
" Equity(3 [2330]) | \n",
" 3000 | \n",
" 243.41 | \n",
" 246.0 | \n",
" 738000.0 | \n",
" \n",
" \n",
" 2018-08-01 13:30:00+08:00 | \n",
" 3 | \n",
" 2330 | \n",
" Equity(3 [2330]) | \n",
" 3500 | \n",
" 244.42 | \n",
" 248.0 | \n",
" 868000.0 | \n",
" \n",
" \n",
" 2018-08-02 13:30:00+08:00 | \n",
" 3 | \n",
" 2330 | \n",
" Equity(3 [2330]) | \n",
" 3500 | \n",
" 244.42 | \n",
" 244.5 | \n",
" 855750.0 | \n",
" \n",
" \n",
" 2018-08-03 13:30:00+08:00 | \n",
" 3 | \n",
" 2330 | \n",
" Equity(3 [2330]) | \n",
" 3500 | \n",
" 244.42 | \n",
" 247.0 | \n",
" 864500.0 | \n",
" \n",
" \n",
" 2018-08-06 13:30:00+08:00 | \n",
" 3 | \n",
" 2330 | \n",
" Equity(3 [2330]) | \n",
" 3500 | \n",
" 244.42 | \n",
" 245.5 | \n",
" 859250.0 | \n",
" \n",
" \n",
" 2018-08-07 13:30:00+08:00 | \n",
" 3 | \n",
" 2330 | \n",
" Equity(3 [2330]) | \n",
" 3500 | \n",
" 244.42 | \n",
" 241.5 | \n",
" 845250.0 | \n",
" \n",
" \n",
" 2018-08-08 13:30:00+08:00 | \n",
" 3 | \n",
" 2330 | \n",
" Equity(3 [2330]) | \n",
" 3500 | \n",
" 244.42 | \n",
" 247.5 | \n",
" 866250.0 | \n",
" \n",
" \n",
" 2018-08-09 13:30:00+08:00 | \n",
" 3 | \n",
" 2330 | \n",
" Equity(3 [2330]) | \n",
" 3500 | \n",
" 244.42 | \n",
" 247.0 | \n",
" 864500.0 | \n",
" \n",
" \n",
" 2018-08-10 13:30:00+08:00 | \n",
" 3 | \n",
" 2330 | \n",
" Equity(3 [2330]) | \n",
" 3500 | \n",
" 244.42 | \n",
" 245.0 | \n",
" 857500.0 | \n",
" \n",
" \n",
" 2018-08-13 13:30:00+08:00 | \n",
" 3 | \n",
" 2330 | \n",
" Equity(3 [2330]) | \n",
" 3500 | \n",
" 244.42 | \n",
" 240.5 | \n",
" 841750.0 | \n",
" \n",
" \n",
" 2018-08-14 13:30:00+08:00 | \n",
" 3 | \n",
" 2330 | \n",
" Equity(3 [2330]) | \n",
" 3500 | \n",
" 244.42 | \n",
" 243.5 | \n",
" 852250.0 | \n",
" \n",
" \n",
" 2018-08-15 13:30:00+08:00 | \n",
" 3 | \n",
" 2330 | \n",
" Equity(3 [2330]) | \n",
" 3500 | \n",
" 244.42 | \n",
" 241.5 | \n",
" 845250.0 | \n",
" \n",
" \n",
" 2018-08-16 13:30:00+08:00 | \n",
" 3 | \n",
" 2330 | \n",
" Equity(3 [2330]) | \n",
" 3500 | \n",
" 244.42 | \n",
" 239.0 | \n",
" 836500.0 | \n",
" \n",
" \n",
" 2018-08-17 13:30:00+08:00 | \n",
" 3 | \n",
" 2330 | \n",
" Equity(3 [2330]) | \n",
" 3500 | \n",
" 244.42 | \n",
" 239.5 | \n",
" 838250.0 | \n",
" \n",
" \n",
" 2018-08-20 13:30:00+08:00 | \n",
" 3 | \n",
" 2330 | \n",
" Equity(3 [2330]) | \n",
" 3500 | \n",
" 244.42 | \n",
" 239.5 | \n",
" 838250.0 | \n",
" \n",
" \n",
" 2018-08-21 13:30:00+08:00 | \n",
" 3 | \n",
" 2330 | \n",
" Equity(3 [2330]) | \n",
" 3500 | \n",
" 244.42 | \n",
" 241.0 | \n",
" 843500.0 | \n",
" \n",
" \n",
" 2018-08-22 13:30:00+08:00 | \n",
" 3 | \n",
" 2330 | \n",
" Equity(3 [2330]) | \n",
" 3500 | \n",
" 244.42 | \n",
" 242.0 | \n",
" 847000.0 | \n",
" \n",
" \n",
" 2018-08-23 13:30:00+08:00 | \n",
" 3 | \n",
" 2330 | \n",
" Equity(3 [2330]) | \n",
" 3500 | \n",
" 244.42 | \n",
" 244.5 | \n",
" 855750.0 | \n",
" \n",
" \n",
" 2018-08-24 13:30:00+08:00 | \n",
" 3 | \n",
" 2330 | \n",
" Equity(3 [2330]) | \n",
" 3500 | \n",
" 244.42 | \n",
" 243.5 | \n",
" 852250.0 | \n",
" \n",
" \n",
" \n",
" "
],
"text/plain": [
" sid symbol asset amount cost_basis \\\n",
"2018-07-26 13:30:00+08:00 3 2330 Equity(3 [2330]) 3000 243.41 \n",
"2018-07-27 13:30:00+08:00 3 2330 Equity(3 [2330]) 3000 243.41 \n",
"2018-07-30 13:30:00+08:00 3 2330 Equity(3 [2330]) 3000 243.41 \n",
"2018-07-31 13:30:00+08:00 3 2330 Equity(3 [2330]) 3000 243.41 \n",
"2018-08-01 13:30:00+08:00 3 2330 Equity(3 [2330]) 3500 244.42 \n",
"2018-08-02 13:30:00+08:00 3 2330 Equity(3 [2330]) 3500 244.42 \n",
"2018-08-03 13:30:00+08:00 3 2330 Equity(3 [2330]) 3500 244.42 \n",
"2018-08-06 13:30:00+08:00 3 2330 Equity(3 [2330]) 3500 244.42 \n",
"2018-08-07 13:30:00+08:00 3 2330 Equity(3 [2330]) 3500 244.42 \n",
"2018-08-08 13:30:00+08:00 3 2330 Equity(3 [2330]) 3500 244.42 \n",
"2018-08-09 13:30:00+08:00 3 2330 Equity(3 [2330]) 3500 244.42 \n",
"2018-08-10 13:30:00+08:00 3 2330 Equity(3 [2330]) 3500 244.42 \n",
"2018-08-13 13:30:00+08:00 3 2330 Equity(3 [2330]) 3500 244.42 \n",
"2018-08-14 13:30:00+08:00 3 2330 Equity(3 [2330]) 3500 244.42 \n",
"2018-08-15 13:30:00+08:00 3 2330 Equity(3 [2330]) 3500 244.42 \n",
"2018-08-16 13:30:00+08:00 3 2330 Equity(3 [2330]) 3500 244.42 \n",
"2018-08-17 13:30:00+08:00 3 2330 Equity(3 [2330]) 3500 244.42 \n",
"2018-08-20 13:30:00+08:00 3 2330 Equity(3 [2330]) 3500 244.42 \n",
"2018-08-21 13:30:00+08:00 3 2330 Equity(3 [2330]) 3500 244.42 \n",
"2018-08-22 13:30:00+08:00 3 2330 Equity(3 [2330]) 3500 244.42 \n",
"2018-08-23 13:30:00+08:00 3 2330 Equity(3 [2330]) 3500 244.42 \n",
"2018-08-24 13:30:00+08:00 3 2330 Equity(3 [2330]) 3500 244.42 \n",
"\n",
" last_sale_price mv \n",
"2018-07-26 13:30:00+08:00 241.0 723000.0 \n",
"2018-07-27 13:30:00+08:00 244.5 733500.0 \n",
"2018-07-30 13:30:00+08:00 245.5 736500.0 \n",
"2018-07-31 13:30:00+08:00 246.0 738000.0 \n",
"2018-08-01 13:30:00+08:00 248.0 868000.0 \n",
"2018-08-02 13:30:00+08:00 244.5 855750.0 \n",
"2018-08-03 13:30:00+08:00 247.0 864500.0 \n",
"2018-08-06 13:30:00+08:00 245.5 859250.0 \n",
"2018-08-07 13:30:00+08:00 241.5 845250.0 \n",
"2018-08-08 13:30:00+08:00 247.5 866250.0 \n",
"2018-08-09 13:30:00+08:00 247.0 864500.0 \n",
"2018-08-10 13:30:00+08:00 245.0 857500.0 \n",
"2018-08-13 13:30:00+08:00 240.5 841750.0 \n",
"2018-08-14 13:30:00+08:00 243.5 852250.0 \n",
"2018-08-15 13:30:00+08:00 241.5 845250.0 \n",
"2018-08-16 13:30:00+08:00 239.0 836500.0 \n",
"2018-08-17 13:30:00+08:00 239.5 838250.0 \n",
"2018-08-20 13:30:00+08:00 239.5 838250.0 \n",
"2018-08-21 13:30:00+08:00 241.0 843500.0 \n",
"2018-08-22 13:30:00+08:00 242.0 847000.0 \n",
"2018-08-23 13:30:00+08:00 244.5 855750.0 \n",
"2018-08-24 13:30:00+08:00 243.5 852250.0 "
]
},
"execution_count": 25,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"positions['mv'] = positions['amount'] * positions['last_sale_price']\n",
"positions.loc[positions.symbol=='2330']"
]
},
{
"cell_type": "markdown",
"id": "b3b1abe6",
"metadata": {},
"source": [
"[Return to Menu](#menu)"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"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.8.13"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
|