Commit df441253 authored by Dr.李's avatar Dr.李

added timing

parent 517485f7
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"id": "fc508832-1cac-4ba2-914f-ed19644fd3e5",
"metadata": {},
"outputs": [],
"source": [
"import sys\n",
"sys.path.append(\"../\")\n",
"import numpy as np\n",
"from fof.utility import *\n",
"from PyFin.api import *"
]
},
{
"cell_type": "markdown",
"id": "77ffba8c-385b-4eea-81f7-a08b54bc128d",
"metadata": {},
"source": [
"## 1.1 Put it all together"
]
},
{
"cell_type": "markdown",
"id": "0caeb90a-6bd1-4fa2-9d75-6bdd83c1b3b2",
"metadata": {},
"source": [
"以下函数,计算在指定观察日,最近一期(季度)的择时胜率分析"
]
},
{
"cell_type": "code",
"execution_count": 13,
"id": "11f4ac54-8a1e-4a23-abb0-785416ff45ed",
"metadata": {},
"outputs": [
{
"ename": "SyntaxError",
"evalue": "closing parenthesis ']' does not match opening parenthesis '(' (Temp/ipykernel_52620/96406359.py, line 6)",
"output_type": "error",
"traceback": [
"\u001b[1;36m File \u001b[1;32m\"C:\\Users\\wegam\\AppData\\Local\\Temp/ipykernel_52620/96406359.py\"\u001b[1;36m, line \u001b[1;32m6\u001b[0m\n\u001b[1;33m asset_portfolios = asset_portfolios[asset_portfolios.REPORTDATE.isin([last_report_date.replace(\"-\", \"\"), report_date.replace(\"-\", \"\")]]\u001b[0m\n\u001b[1;37m ^\u001b[0m\n\u001b[1;31mSyntaxError\u001b[0m\u001b[1;31m:\u001b[0m closing parenthesis ']' does not match opening parenthesis '('\n"
]
}
],
"source": [
"def create_timing_analysis(security_ids, reprot_date, benchmark=\"2070000191\"):\n",
" last_report_date = nearest_report_date(advanceDate(report_date, \"-1d\").strftime(\"%Y%m%d\"), freq=\"Q\", method=\"backward\")\n",
"\n",
" index_return = index_rtn(benchmark, last_report_date, report_date)[\"rtn\"].at[0]\n",
" asset_portfolios = fd_assetportfolio(security_ids, last_report_date, report_date).sort_values(\"REPORTDATE\").fillna(0)\n",
" asset_portfolios = asset_portfolios[asset_portfolios.REPORTDATE.isin([last_report_date.replace(\"-\", \"\"), report_date.replace(\"-\", \"\")]]\n",
"\n",
" periods_count = asset_portfolios.groupby(\"SECURITYID\")[\"REPORTDATE\"].count()\n",
" periods_count = periods_count[periods_count >= 2]\n",
" asset_portfolios = asset_portfolios[asset_portfolios.SECURITYID.isin(periods_count.index)]\n",
" groups = asset_portfolios.groupby(\"SECURITYID\")\n",
" \n",
" records = []\n",
" for k, g in groups:\n",
" begin_date = g[\"REPORTDATE\"].iloc[0]\n",
" end_date = g[\"REPORTDATE\"].iloc[1]\n",
" equity_begin = g[\"EQUITYINVERTO\"].iloc[0]\n",
" equity_end = g[\"EQUITYINVERTO\"].iloc[1]\n",
" adjusted_equity_end = equity_end / (1. + index_return)\n",
" is_win = ((adjusted_equity_end - equity_begin) * index_return) > 0\n",
" timing_rtn = (adjusted_equity_end - equity_begin) * index_return / 100.\n",
" records.append(\n",
" dict(SECURITYID=k, index_rtn=index_return, begin_date=begin_date, end_date=end_date, equity_begin=equity_begin, equity_end=equity_end, adjusted_equity_end=adjusted_equity_end, is_win=is_win, timing_rtn=timing_rtn)\n",
" )\n",
" df = pd.DataFrame.from_records(records)\n",
" return df"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "7995d877-d609-4cca-97aa-e7acd73850d0",
"metadata": {},
"outputs": [],
"source": [
"report_date = \"2021-12-31\"\n",
"security_ids = list(fd_basicinfo(trade_dt=report_date).SECURITYID.unique())"
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "4f833e84-1224-47cb-a811-a6d18e7077ff",
"metadata": {},
"outputs": [],
"source": [
"report = create_timing_analysis(security_ids, report_date) "
]
},
{
"cell_type": "markdown",
"id": "f3335c3b-395b-4373-97f2-ae5b59a451fe",
"metadata": {},
"source": [
"* `equity_begin`: 期初股票持仓\n",
"* `equity_end`: 期末股票持仓\n",
"* `adjusted_equity_end`: 调整期末股票持仓\n",
"* `is_win`: 是否择时获胜\n",
"* `timing_rtn`: 择时收益贡献"
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "ed8f853b-0ac7-49eb-9840-422f2ccfd23e",
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>SECURITYID</th>\n",
" <th>index_rtn</th>\n",
" <th>begin_date</th>\n",
" <th>end_date</th>\n",
" <th>equity_begin</th>\n",
" <th>equity_end</th>\n",
" <th>adjusted_equity_end</th>\n",
" <th>is_win</th>\n",
" <th>timing_rtn</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>0</th>\n",
" <td>1030000001</td>\n",
" <td>0.028536</td>\n",
" <td>20210930</td>\n",
" <td>20211231</td>\n",
" <td>90.96</td>\n",
" <td>91.80</td>\n",
" <td>89.253116</td>\n",
" <td>False</td>\n",
" <td>-0.000487</td>\n",
" </tr>\n",
" <tr>\n",
" <th>1</th>\n",
" <td>1030000004</td>\n",
" <td>0.028536</td>\n",
" <td>20210930</td>\n",
" <td>20211231</td>\n",
" <td>93.69</td>\n",
" <td>93.23</td>\n",
" <td>90.643442</td>\n",
" <td>False</td>\n",
" <td>-0.000869</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2</th>\n",
" <td>1030000005</td>\n",
" <td>0.028536</td>\n",
" <td>20210930</td>\n",
" <td>20211231</td>\n",
" <td>93.56</td>\n",
" <td>87.32</td>\n",
" <td>84.897408</td>\n",
" <td>False</td>\n",
" <td>-0.002472</td>\n",
" </tr>\n",
" <tr>\n",
" <th>3</th>\n",
" <td>1030000006</td>\n",
" <td>0.028536</td>\n",
" <td>20210930</td>\n",
" <td>20211231</td>\n",
" <td>70.60</td>\n",
" <td>67.78</td>\n",
" <td>65.899523</td>\n",
" <td>False</td>\n",
" <td>-0.001341</td>\n",
" </tr>\n",
" <tr>\n",
" <th>4</th>\n",
" <td>1030000007</td>\n",
" <td>0.028536</td>\n",
" <td>20210930</td>\n",
" <td>20211231</td>\n",
" <td>89.93</td>\n",
" <td>91.63</td>\n",
" <td>89.087833</td>\n",
" <td>False</td>\n",
" <td>-0.000240</td>\n",
" </tr>\n",
" <tr>\n",
" <th>...</th>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>13465</th>\n",
" <td>2030019986</td>\n",
" <td>0.028536</td>\n",
" <td>20211203</td>\n",
" <td>20211231</td>\n",
" <td>2.20</td>\n",
" <td>0.00</td>\n",
" <td>0.000000</td>\n",
" <td>False</td>\n",
" <td>-0.000628</td>\n",
" </tr>\n",
" <tr>\n",
" <th>13466</th>\n",
" <td>2030020009</td>\n",
" <td>0.028536</td>\n",
" <td>20211222</td>\n",
" <td>20211231</td>\n",
" <td>1.02</td>\n",
" <td>0.00</td>\n",
" <td>0.000000</td>\n",
" <td>False</td>\n",
" <td>-0.000291</td>\n",
" </tr>\n",
" <tr>\n",
" <th>13467</th>\n",
" <td>2030020055</td>\n",
" <td>0.028536</td>\n",
" <td>20211230</td>\n",
" <td>20211231</td>\n",
" <td>79.39</td>\n",
" <td>0.00</td>\n",
" <td>0.000000</td>\n",
" <td>False</td>\n",
" <td>-0.022654</td>\n",
" </tr>\n",
" <tr>\n",
" <th>13468</th>\n",
" <td>2030020163</td>\n",
" <td>0.028536</td>\n",
" <td>20211216</td>\n",
" <td>20211231</td>\n",
" <td>13.01</td>\n",
" <td>0.00</td>\n",
" <td>0.000000</td>\n",
" <td>False</td>\n",
" <td>-0.003712</td>\n",
" </tr>\n",
" <tr>\n",
" <th>13469</th>\n",
" <td>2030020298</td>\n",
" <td>0.028536</td>\n",
" <td>20211230</td>\n",
" <td>20211231</td>\n",
" <td>18.13</td>\n",
" <td>0.00</td>\n",
" <td>0.000000</td>\n",
" <td>False</td>\n",
" <td>-0.005173</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>13470 rows × 9 columns</p>\n",
"</div>"
],
"text/plain": [
" SECURITYID index_rtn begin_date end_date equity_begin equity_end \\\n",
"0 1030000001 0.028536 20210930 20211231 90.96 91.80 \n",
"1 1030000004 0.028536 20210930 20211231 93.69 93.23 \n",
"2 1030000005 0.028536 20210930 20211231 93.56 87.32 \n",
"3 1030000006 0.028536 20210930 20211231 70.60 67.78 \n",
"4 1030000007 0.028536 20210930 20211231 89.93 91.63 \n",
"... ... ... ... ... ... ... \n",
"13465 2030019986 0.028536 20211203 20211231 2.20 0.00 \n",
"13466 2030020009 0.028536 20211222 20211231 1.02 0.00 \n",
"13467 2030020055 0.028536 20211230 20211231 79.39 0.00 \n",
"13468 2030020163 0.028536 20211216 20211231 13.01 0.00 \n",
"13469 2030020298 0.028536 20211230 20211231 18.13 0.00 \n",
"\n",
" adjusted_equity_end is_win timing_rtn \n",
"0 89.253116 False -0.000487 \n",
"1 90.643442 False -0.000869 \n",
"2 84.897408 False -0.002472 \n",
"3 65.899523 False -0.001341 \n",
"4 89.087833 False -0.000240 \n",
"... ... ... ... \n",
"13465 0.000000 False -0.000628 \n",
"13466 0.000000 False -0.000291 \n",
"13467 0.000000 False -0.022654 \n",
"13468 0.000000 False -0.003712 \n",
"13469 0.000000 False -0.005173 \n",
"\n",
"[13470 rows x 9 columns]"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"report"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "59db38a5-0cae-4c17-854f-b8084e4828dd",
"metadata": {},
"outputs": [],
"source": []
}
],
"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.9.7"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
...@@ -3,6 +3,7 @@ import calendar ...@@ -3,6 +3,7 @@ import calendar
import pymssql import pymssql
import sqlalchemy as sa import sqlalchemy as sa
import numpy as np
import pandas as pd import pandas as pd
...@@ -63,7 +64,7 @@ def read_sql(query, source="mssql"): ...@@ -63,7 +64,7 @@ def read_sql(query, source="mssql"):
return pd.read_sql(query, con=engine) return pd.read_sql(query, con=engine)
def nearest_report_date(date, freq="Q"): def nearest_report_date(date, freq="Q", method="forward"):
if len(date) == 10: if len(date) == 10:
date = date.replace("-", "") date = date.replace("-", "")
...@@ -71,10 +72,15 @@ def nearest_report_date(date, freq="Q"): ...@@ -71,10 +72,15 @@ def nearest_report_date(date, freq="Q"):
year = int(date[0:4]) year = int(date[0:4])
last_year = year last_year = year
if method == "forward":
add = 1
else:
add = 0
if freq == "Q": if freq == "Q":
q = (mm // 3 + 1) * 3 - 3 q = (mm // 3 + add) * 3 - 3
else: else:
q = (mm // 6 + 1) * 6 - 6 q = (mm // 6 + add) * 6 - 6
if q <= 0: if q <= 0:
q += 12 q += 12
...@@ -217,8 +223,8 @@ def fd_assetportfolio(security_ids, report_dates_begin, report_dates_end=None): ...@@ -217,8 +223,8 @@ def fd_assetportfolio(security_ids, report_dates_begin, report_dates_end=None):
query = f""" query = f"""
SELECT SECODE as SECURITYID, REPORTDATE, BDRTO, CONVBDRTO, EQUITYINVERTO FROM TQ_FD_ASSETPORTFOLIO SELECT SECODE as SECURITYID, REPORTDATE, BDRTO, CONVBDRTO, EQUITYINVERTO FROM TQ_FD_ASSETPORTFOLIO
WHERE WHERE
REPORTDATE >= '{report_dates_begin}' AND REPORTDATE >= '{_to_yyyymmdd(report_dates_begin)}' AND
REPORTDATE <= '{report_dates_end}' AND REPORTDATE <= '{_to_yyyymmdd(report_dates_end)}' AND
ISVALID = 1 AND ISVALID = 1 AND
SECODE in ({sec_id_strs}) SECODE in ({sec_id_strs})
""" """
...@@ -277,15 +283,21 @@ def fd_skdetail(security_ids, trade_dt): ...@@ -277,15 +283,21 @@ def fd_skdetail(security_ids, trade_dt):
p_id_strs = _join_ids(security_ids) p_id_strs = _join_ids(security_ids)
query = f""" query = f"""
SELECT SECODE as pid, SKCODE as security_code, SKNAME, HOLDMKTCAP, HOLDAMT, NAVRTO FROM TQ_FD_SKDETAIL SELECT SECODE as pid, PUBLISHDATE, SKCODE as security_code, SKNAME, HOLDMKTCAP, HOLDAMT, NAVRTO FROM TQ_FD_SKDETAIL
WHERE WHERE
ENDDATE = '{trade_dt}' AND ENDDATE = '{trade_dt}' AND
ISVALID = 1 AND ISVALID = 1 AND
SECODE in ({p_id_strs}) SECODE in ({p_id_strs})
""" """
df = read_sql(query).sort_values("security_code") groups = read_sql(query).sort_values("security_code").groupby("pid")
total_value = df.HOLDMKTCAP.sum() dfs = []
df["weight"] = df.HOLDMKTCAP / total_value for k, g in groups:
g = g[g.PUBLISHDATE == np.max(g.PUBLISHDATE)]
total_value = g.HOLDMKTCAP.sum()
g["weight"] = g.HOLDMKTCAP / total_value
dfs.append(g)
df = pd.concat(dfs)
del df["PUBLISHDATE"]
return df.reset_index(drop=True) return df.reset_index(drop=True)
...@@ -530,3 +542,20 @@ def read_factors(security_ids, trade_dt, factors): ...@@ -530,3 +542,20 @@ def read_factors(security_ids, trade_dt, factors):
flag = 1 flag = 1
""" """
return read_sql(query, source="mysql").sort_values("security_code").reset_index(drop=True) return read_sql(query, source="mysql").sort_values("security_code").reset_index(drop=True)
def index_rtn(security_ids, begin_date, end_date):
sec_id_strs = _join_ids(security_ids)
query = f"""
SELECT security_code, min(trade_date) AS begin_date, max(trade_date) AS end_date, exp(sum(ln(1 + change_pct / 100.))) - 1.0 AS rtn FROM index_daily_price
WHERE
trade_date >= '{_to_yyyy_mm_dd(begin_date)}' AND
trade_date <= '{_to_yyyy_mm_dd(end_date)}' AND
security_code in ({sec_id_strs}) AND
flag = 1
GROUP BY
security_code
"""
df = read_sql(query, source="mysql").sort_values("security_code").reset_index(drop=True)
return df
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment