{ "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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
sidsymbolamountdtpriceorder_idassetcommission
2018-07-25 13:30:00+08:00323301002018-07-25 13:30:00+08:00240.5f1148fd31aa84be5b4d7e27c9c858a39Equity(3 [2330])None
2018-07-27 13:30:00+08:00011011002018-07-27 13:30:00+08:0040.3d4971027bce4491db4eeb0cf8655c4bcEquity(0 [1101])None
2018-07-31 13:30:00+08:00112161002018-07-31 13:30:00+08:0080.8ac333a81f710428e83c5ccacc8ce72e2Equity(1 [1216])None
\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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
sidsymbolassetamountcost_basislast_sale_price
2018-07-25 13:30:00+08:0032330Equity(3 [2330])1000240.842713240.5
2018-07-26 13:30:00+08:0032330Equity(3 [2330])1000240.842713241.0
2018-07-27 13:30:00+08:0032330Equity(3 [2330])500241.191125244.5
2018-07-30 13:30:00+08:0032330Equity(3 [2330])500241.191125245.5
2018-07-31 13:30:00+08:0032330Equity(3 [2330])-300245.065200246.0
2018-08-01 13:30:00+08:0032330Equity(3 [2330])-300245.065200248.0
\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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
gross_leverageportfolio_valueending_cash
2018-07-25 13:30:00+08:001.9740229.971949e+05970010.309730
2018-07-26 13:30:00+08:002.0001919.898798e+05970010.309730
2018-07-27 13:30:00+08:002.4816041.007198e+06460768.172293
\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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
sidsymbolassetamountcost_basislast_sale_price
2018-07-25 13:30:00+08:0032330Equity(3 [2330])4149240.842712240.5
2018-07-25 13:30:00+08:0022317Equity(2 [2317])-1173782.58215382.7
\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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
sidsymboliddtreasoncreatedamountfilledcommissionstoplimitstop_reachedlimit_reachedassetstatus
2018-07-25 13:30:00+08:00323302f3d2c75c6a14f0982e20325263d801e2018-07-25 13:30:00+08:00None2018-07-24 13:30:00+08:002074688538250184476.532188NoneNoneFalseFalseEquity(3 [2330])0
2018-07-25 13:30:00+08:00423570c8c942572bb4ca9a8ce29ad629133c42018-07-25 13:30:00+08:00None2018-07-24 13:30:00+08:0011385195317519778.347944NoneNoneFalseFalseEquity(4 [2357])0
2018-07-25 13:30:00+08:0052454e69b7d9d8b164b4d9939038ca0c855a02018-07-25 13:30:00+08:00None2018-07-25 13:30:00+08:00190400.000000NoneNoneFalseFalseEquity(5 [2454])0
2018-07-25 13:30:00+08:00223178ba7f1517291473b8bf6649451c2c63f2018-07-25 13:30:00+08:00None2018-07-25 13:30:00+08:00604500.000000NoneNoneFalseFalseEquity(2 [2317])0
2018-07-25 13:30:00+08:000110162895a53e99b4f5d96a2f178705220fd2018-07-25 13:30:00+08:00None2018-07-25 13:30:00+08:001108600.000000NoneNoneFalseFalseEquity(0 [1101])0
\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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
sidsymboliddtreasoncreatedamountfilledcommissionstoplimitstop_reachedlimit_reachedassetstatus
2018-07-25 13:30:00+08:0001101ae91c552e8444d46ba046678ef6d57352018-07-25 13:30:00+08:00None2018-07-25 13:30:00+08:00100000.0NoneNoneFalseFalseEquity(0 [1101])0
2018-07-26 13:30:00+08:0001101ae91c552e8444d46ba046678ef6d57352018-07-26 13:30:00+08:00None2018-07-25 13:30:00+08:0011001100445.5NoneNoneFalseFalseEquity(0 [1101])1
\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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
mdatecoidclose_d
252018-07-252330240.5
262018-07-262330241.0
\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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
sidsymbolamountdtpriceorder_idassetcommission
2018-07-26 13:30:00+08:000110111002018-07-26 13:30:00+08:0040.5ae91c552e8444d46ba046678ef6d5735Equity(0 [1101])None
2018-07-26 13:30:00+08:003233020002018-07-26 13:30:00+08:00241.02c71621d421a4b51838e0bc65f9e949bEquity(3 [2330])None
\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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
mdatecoidclose_d
412018-08-162330239.0
422018-08-172330239.5
\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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
sidsymbolamountdtpriceorder_idassetcommission
2018-08-17 13:30:00+08:003233020052018-08-17 13:30:00+08:00239.52363ca6eedd441e0ab297fe80d2f5fefEquity(3 [2330])None
\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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
sidsymboliddtreasoncreatedamountfilledcommissionstoplimitstop_reachedlimit_reachedassetstatus
2018-07-24 13:30:00+08:0001101e6212ce9c29b467d9d4372a7f9ec8bb22018-07-24 13:30:00+08:00None2018-07-24 13:30:00+08:00100000.0NoneNoneFalseFalseEquity(0 [1101])0
2018-07-25 13:30:00+08:0001101e6212ce9c29b467d9d4372a7f9ec8bb22018-07-25 13:30:00+08:00None2018-07-24 13:30:00+08:0010001000451.0NoneNoneFalseFalseEquity(0 [1101])1
\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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
sidsymbolassetamountcost_basislast_sale_price
2018-07-25 13:30:00+08:0001101Equity(0 [1101])100045.55145.1
2018-07-26 13:30:00+08:0001101Equity(0 [1101])110041.40040.5
\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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
sidsymboliddtreasoncreatedamountfilledcommissionstoplimitstop_reachedlimit_reachedassetstatus
2018-07-25 13:30:00+08:0032330b04afe6c14f440c4bbc460cdb6fea2fd2018-07-25 13:30:00+08:00None2018-07-25 13:30:00+08:00200000.0NoneNoneFalseFalseEquity(3 [2330])0
2018-07-25 13:30:00+08:00323301097aa119bbc4f2ebe42eb627c02ed0f2018-07-25 13:30:00+08:00None2018-07-25 13:30:00+08:00100000.0NoneNoneFalseFalseEquity(3 [2330])0
2018-07-26 13:30:00+08:0032330b04afe6c14f440c4bbc460cdb6fea2fd2018-07-26 13:30:00+08:00None2018-07-25 13:30:00+08:00200020004820.0NoneNoneFalseFalseEquity(3 [2330])1
2018-07-26 13:30:00+08:00323301097aa119bbc4f2ebe42eb627c02ed0f2018-07-26 13:30:00+08:00None2018-07-25 13:30:00+08:00100010002410.0NoneNoneFalseFalseEquity(3 [2330])1
2018-07-31 13:30:00+08:00323307eaa433315ec438b9837695951a0b1262018-07-31 13:30:00+08:00None2018-07-31 13:30:00+08:0050000.0NoneNoneFalseFalseEquity(3 [2330])0
2018-08-01 13:30:00+08:00323307eaa433315ec438b9837695951a0b1262018-08-01 13:30:00+08:00None2018-07-31 13:30:00+08:005005001240.0NoneNoneFalseFalseEquity(3 [2330])1
\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", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
sidsymbolassetamountcost_basislast_sale_pricemv
2018-07-26 13:30:00+08:0032330Equity(3 [2330])3000243.41241.0723000.0
2018-07-27 13:30:00+08:0032330Equity(3 [2330])3000243.41244.5733500.0
2018-07-30 13:30:00+08:0032330Equity(3 [2330])3000243.41245.5736500.0
2018-07-31 13:30:00+08:0032330Equity(3 [2330])3000243.41246.0738000.0
2018-08-01 13:30:00+08:0032330Equity(3 [2330])3500244.42248.0868000.0
2018-08-02 13:30:00+08:0032330Equity(3 [2330])3500244.42244.5855750.0
2018-08-03 13:30:00+08:0032330Equity(3 [2330])3500244.42247.0864500.0
2018-08-06 13:30:00+08:0032330Equity(3 [2330])3500244.42245.5859250.0
2018-08-07 13:30:00+08:0032330Equity(3 [2330])3500244.42241.5845250.0
2018-08-08 13:30:00+08:0032330Equity(3 [2330])3500244.42247.5866250.0
2018-08-09 13:30:00+08:0032330Equity(3 [2330])3500244.42247.0864500.0
2018-08-10 13:30:00+08:0032330Equity(3 [2330])3500244.42245.0857500.0
2018-08-13 13:30:00+08:0032330Equity(3 [2330])3500244.42240.5841750.0
2018-08-14 13:30:00+08:0032330Equity(3 [2330])3500244.42243.5852250.0
2018-08-15 13:30:00+08:0032330Equity(3 [2330])3500244.42241.5845250.0
2018-08-16 13:30:00+08:0032330Equity(3 [2330])3500244.42239.0836500.0
2018-08-17 13:30:00+08:0032330Equity(3 [2330])3500244.42239.5838250.0
2018-08-20 13:30:00+08:0032330Equity(3 [2330])3500244.42239.5838250.0
2018-08-21 13:30:00+08:0032330Equity(3 [2330])3500244.42241.0843500.0
2018-08-22 13:30:00+08:0032330Equity(3 [2330])3500244.42242.0847000.0
2018-08-23 13:30:00+08:0032330Equity(3 [2330])3500244.42244.5855750.0
2018-08-24 13:30:00+08:0032330Equity(3 [2330])3500244.42243.5852250.0
\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 }