Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
fof
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Dr.李
fof
Commits
df441253
Commit
df441253
authored
Mar 26, 2022
by
Dr.李
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
added timing
parent
517485f7
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
393 additions
and
9 deletions
+393
-9
010 择时能力.ipynb
20220326/010 择时能力.ipynb
+355
-0
utility.py
fof/utility.py
+38
-9
No files found.
20220326/010 择时能力.ipynb
0 → 100644
View file @
df441253
{
"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
}
fof/utility.py
View file @
df441253
...
...
@@ -3,6 +3,7 @@ import calendar
import
pymssql
import
sqlalchemy
as
sa
import
numpy
as
np
import
pandas
as
pd
...
...
@@ -63,7 +64,7 @@ def read_sql(query, source="mssql"):
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
:
date
=
date
.
replace
(
"-"
,
""
)
...
...
@@ -71,10 +72,15 @@ def nearest_report_date(date, freq="Q"):
year
=
int
(
date
[
0
:
4
])
last_year
=
year
if
method
==
"forward"
:
add
=
1
else
:
add
=
0
if
freq
==
"Q"
:
q
=
(
mm
//
3
+
1
)
*
3
-
3
q
=
(
mm
//
3
+
add
)
*
3
-
3
else
:
q
=
(
mm
//
6
+
1
)
*
6
-
6
q
=
(
mm
//
6
+
add
)
*
6
-
6
if
q
<=
0
:
q
+=
12
...
...
@@ -217,8 +223,8 @@ def fd_assetportfolio(security_ids, report_dates_begin, report_dates_end=None):
query
=
f
"""
SELECT SECODE as SECURITYID, REPORTDATE, BDRTO, CONVBDRTO, EQUITYINVERTO FROM TQ_FD_ASSETPORTFOLIO
WHERE
REPORTDATE >= '{
report_dates_begin
}' AND
REPORTDATE <= '{
report_dates_end
}' AND
REPORTDATE >= '{
_to_yyyymmdd(report_dates_begin)
}' AND
REPORTDATE <= '{
_to_yyyymmdd(report_dates_end)
}' AND
ISVALID = 1 AND
SECODE in ({sec_id_strs})
"""
...
...
@@ -277,15 +283,21 @@ def fd_skdetail(security_ids, trade_dt):
p_id_strs
=
_join_ids
(
security_ids
)
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
ENDDATE = '{trade_dt}' AND
ISVALID = 1 AND
SECODE in ({p_id_strs})
"""
df
=
read_sql
(
query
)
.
sort_values
(
"security_code"
)
total_value
=
df
.
HOLDMKTCAP
.
sum
()
df
[
"weight"
]
=
df
.
HOLDMKTCAP
/
total_value
groups
=
read_sql
(
query
)
.
sort_values
(
"security_code"
)
.
groupby
(
"pid"
)
dfs
=
[]
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
)
...
...
@@ -530,3 +542,20 @@ def read_factors(security_ids, trade_dt, factors):
flag = 1
"""
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
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment