请 [注册] 或 [登录]  | 返回主站

量化交易吧 /  量化平台 帖子:3364712 新帖:0

【第一次玩】我就是要买便宜股系列

SCSDV_d发表于:5 月 10 日 01:01回复(1)

第一次玩这个策略,实测了一个便宜股筛选的策略,半年调仓一次,选择 0< PE< 10,0< PE<1.5,股息率 > 3% 排名前列的股票。中间浪费了一些手续费,收益率还是符合要求,但是发现终究还是要看天吃饭呀~

  • 目标:获取当天最便宜的 10 只股票,把钱分摊进去
  • 标准:
    • 0 < PE < 10
    • 0 < PB < 1.5
    • 近期股息率 > 3%
    • 同行业不得超过 3 家
    • 如果没有选够 10 只,则空仓
  • 周期:半年进行一次调仓
  • 测试时间:2013 - 2018
import pandas as pd
from jqdata import *
from datetime import date, timedelta
import math
# 获取所有股票当天 / 近期的 PE, PB, ROE
q = query(
    valuation.code,
    valuation.pe_ratio,
    valuation.pb_ratio
)
df = get_fundamentals(q)
df = df[df["pe_ratio"] > 0]
df = df[df["pe_ratio"] < 10]
df = df[df["pb_ratio"] > 0]
df = df[df["pb_ratio"] < 1.5]
def DividendRatio(security_list,end_date,count=1):
    '''查询股息率(日更新)
    输入:股票池,截止日期,获取数量
    输出:panel结构,单位:1'''
    trade_days = get_trade_days(end_date=end_date,count = count)
    security_list.sort()
    secu_list = [x[:6] for x in security_list]
    code_df = jy.run_query(query(
         jy.SecuMain.InnerCode,jy.SecuMain.SecuCode,
    #     jy.SecuMain.ChiName,jy.SecuMain.CompanyCode
        ).filter(
        jy.SecuMain.SecuCode.in_(secu_list),jy.SecuMain.SecuCategory==1).order_by(jy.SecuMain.SecuCode))
    code_df['code'] = security_list
    df = jy.run_query(query(
#         jy.LC_DIndicesForValuation    #得到整表
        jy.LC_DIndicesForValuation.InnerCode,
                jy.LC_DIndicesForValuation.TradingDay,
                 jy.LC_DIndicesForValuation.DividendRatio,
                ).filter(jy.LC_DIndicesForValuation.InnerCode.in_(code_df.InnerCode),
                        jy.LC_DIndicesForValuation.TradingDay.in_(trade_days)
                        ))
    f_df = df.merge(code_df,on='InnerCode').set_index(['TradingDay','code']).drop(['InnerCode','SecuCode'],axis=1)
    panel = f_df.to_panel()
    return panel
df = df.sort_values(["code"], ascending=[True])
yesterday = date.today() - timedelta(1)
dividend_ratio_panel = DividendRatio(df.code.tolist(), yesterday.strftime("%Y-%m-%d"))
dividend_ratio = dividend_ratio_panel.major_xs(yesterday.strftime("%Y-%m-%d"))["DividendRatio"].tolist()
/opt/conda/lib/python3.5/site-packages/sqlalchemy/dialects/mysql/base.py:1936: SAWarning: MariaDB (10, 2, 6) before 10.2.9 has known issues regarding CHECK constraints, which impact handling of NULL values with SQLAlchemy's boolean datatype (MDEV-13596). An additional issue prevents proper migrations of columns with CHECK constraints (MDEV-11114).  Please upgrade to MariaDB 10.2.9 or greater, or use the MariaDB 10.1 series, to avoid these issues.
  "series, to avoid these issues." % (mdb_version, ))
/opt/conda/lib/python3.5/site-packages/ipykernel_launcher.py:23: DeprecationWarning: 
Panel is deprecated and will be removed in a future version.
The recommended way to represent these types of 3-dimensional data are with a MultiIndex on a DataFrame, via the Panel.to_frame() method
Alternatively, you can use the xarray package http://xarray.pydata.org/en/stable/.
Pandas provides a `.to_xarray()` method to help automate this conversion.

df["dividend_ratio"] = dividend_ratio
df = df.dropna()
df = df[df["dividend_ratio"] > 0.03]
industry_df = finance.run_query(
        query(
            finance.STK_COMPANY_INFO.code,
            finance.STK_COMPANY_INFO.industry_id
        ).filter(
            finance.STK_COMPANY_INFO.code.in_(df["code"].tolist())
        )
    )
df["industry_id"] = industry_df["industry_id"].tolist()
df_sorted = df.sort_values(["pe_ratio", "pb_ratio", "dividend_ratio"], ascending=[True, True, False])
def get_industry_id(code):
    df = finance.run_query(
        query(
            finance.STK_COMPANY_INFO.industry_id
        ).filter(
            finance.STK_COMPANY_INFO.code == code
        )
    )
    
    return df["industry_id"][0]

def get_six_stocks(sorted_stock_list, max_stock):
    stock_list_info = []
    stock_list = []
    occur_dict = {}
    for loc in range(sorted_stock_list.shape[0]):
        field = get_industry_id(sorted_stock_list.iloc[loc]["code"])
        if field in occur_dict:
            if occur_dict[field] >= max_stock * 0.3:
                continue
            else:
                occur_dict[field] += 1
                stock_list_info.append(sorted_stock_list.iloc[loc])
                stock_list.append(sorted_stock_list.iloc[loc]["code"])
        else:
            stock_list_info.append(sorted_stock_list.iloc[loc])
            stock_list.append(sorted_stock_list.iloc[loc]["code"])
            occur_dict[field] = 1
        if len(stock_list) >= max_stock:
            break
    return stock_list_info, stock_list
stock_list_info, stock_list = get_six_stocks(df_sorted, 10)
stock_list
['000016.XSHE',
 '600708.XSHG',
 '600240.XSHG',
 '000785.XSHE',
 '000825.XSHE',
 '000055.XSHE',
 '000488.XSHE',
 '600383.XSHG',
 '600808.XSHG',
 '002680.XSHE']
# 将 sum_price 中的钱平均分到这些股票上面
def buy_stock(stock_list, sum_price):
    # 获取 stock_list 中股票的当日价格
    price_dict = history(1, unit='1d', field='avg', security_list=stock_list, df=False, skip_paused=False, fq='pre')
    for stock in price_dict.keys():
        price_dict[stock] = price_dict[stock][0]
    # 将 sum_price 平均分配到这些股票上
    sum_price_dict = {}
    per_price = sum_price / len(price_dict)
    for stock in price_dict.keys():
        sum_price_dict[stock] = math.floor(per_price / price_dict[stock] / 100)
    sum_value = 0
    for stock in sum_price_dict.keys():
        sum_value += sum_price_dict[stock] * price_dict[stock]*100
    res_value = sum_price - sum_value
    return price_dict, sum_price_dict, res_value
(datetime.strptime("2018-09-12", "%Y-%m-%d").date()- timedelta(1)).strftime("%Y-%m-%d")
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-27-a0c3148a8241> in <module>()
----> 1 (datetime.strptime("2018-09-12", "%Y-%m-%d").date()- timedelta(1)).strftime("%Y-%m-%d")

AttributeError: module 'datetime' has no attribute 'strptime'
dividend_ratio_panel.major_xs(dividend_ratio_panel.major_axis[0])
.dataframe thead tr:only-child th { text-align: right; } .dataframe thead th { text-align: left; } .dataframe tbody tr th { vertical-align: top; }
DividendRatio
code
000001.XSHE 0.012546
000006.XSHE 0.035842
000016.XSHE 0.047368
000030.XSHE 0.039463
000031.XSHE 0.011702
000036.XSHE 0.114679
000040.XSHE 0.004004
000042.XSHE 0.015129
000043.XSHE 0.016103
000046.XSHE 0.029240
000055.XSHE 0.038128
000059.XSHE NaN
000069.XSHE 0.053476
000402.XSHE 0.048387
000415.XSHE 0.015625
000488.XSHE 0.057614
000501.XSHE 0.008155
000537.XSHE 0.018732
000552.XSHE 0.038462
000553.XSHE 0.006300
000581.XSHE 0.068926
000587.XSHE NaN
000625.XSHE 0.074210
000631.XSHE 0.109541
000656.XSHE 0.046468
000667.XSHE 0.011682
000671.XSHE 0.009843
000683.XSHE 0.008177
000708.XSHE 0.032609
000718.XSHE 0.035461
... ...
601166.XSHG 0.041854
601169.XSHG 0.045486
601186.XSHG 0.016886
601222.XSHG 0.009685
601229.XSHG 0.030525
601288.XSHG 0.043430
601328.XSHG 0.049497
601390.XSHG 0.015087
601398.XSHG 0.044022
601577.XSHG NaN
601588.XSHG 0.044534
601599.XSHG 0.038732
601633.XSHG 0.027869
601636.XSHG 0.080950
601666.XSHG NaN
601668.XSHG 0.029704
601678.XSHG 0.039265
601699.XSHG 0.036055
601800.XSHG 0.019383
601818.XSHG 0.045939
601828.XSHG 0.032190
601838.XSHG 0.033533
601900.XSHG 0.029767
601939.XSHG 0.041810
601988.XSHG 0.048619
601997.XSHG 0.029281
601998.XSHG 0.045313
603035.XSHG 0.019696
603518.XSHG 0.011889
603766.XSHG 0.104216

194 rows × 1 columns

df["pe_ratio_rank"] = df["pe_ratio"].rank(ascending=0,method='max')
df.sort_values(["pe_ratio_rank"])
.dataframe thead tr:only-child th { text-align: right; } .dataframe thead th { text-align: left; } .dataframe tbody tr th { vertical-align: top; }
code pe_ratio pb_ratio dividend_ratio industry_id pe_ratio_rank
2618 600611.XSHG 9.9587 1.0058 0.032432 G54 1.0
143 000552.XSHE 9.7008 0.8392 0.038462 B06 2.0
2673 600676.XSHG 9.6030 0.8089 0.031320 G54 3.0
3024 601567.XSHG 9.5901 1.1056 0.051370 C40 4.0
2226 600133.XSHG 9.5514 0.9095 0.037281 E48 5.0
2629 600622.XSHG 9.2769 0.9909 0.033866 K70 6.0
2426 600368.XSHG 9.2709 1.0333 0.035727 G54 7.0
2807 600820.XSHG 9.2249 0.9210 0.032550 E48 8.0
2366 600297.XSHG 9.1467 1.0280 0.033482 F52 9.0
3440 603766.XSHG 9.1353 1.3392 0.104216 C37 10.0
2952 601088.XSHG 9.1030 1.3714 0.045500 B06 11.0
2342 600269.XSHG 9.0497 0.6414 0.044271 G54 12.0
554 002091.XSHE 8.9780 1.0402 0.041754 F51 13.0
256 000708.XSHE 8.9647 0.9965 0.032609 C31 14.0
216 000656.XSHE 8.8436 1.4560 0.046468 K70 15.0
2431 600373.XSHG 8.8012 1.0625 0.041494 R85 16.0
2142 600035.XSHG 8.7846 0.8127 0.045367 G54 17.0
3029 601599.XSHG 8.7359 0.9911 0.038732 C17 18.0
856 002394.XSHE 8.6363 1.0396 0.079365 C17 19.0
2988 601216.XSHG 8.5331 1.4853 0.070370 C26 20.0
465 002002.XSHE 8.5007 1.3164 0.036365 C26 21.0
2932 601006.XSHG 8.4271 1.1652 0.059569 G53 22.0
2738 600743.XSHG 8.3743 0.6763 0.048544 K70 23.0
2902 600970.XSHG 8.3212 1.2409 0.030039 E48 24.0
2917 600987.XSHG 8.3060 1.3539 0.034696 C17 25.0
2575 600565.XSHG 8.2019 0.8504 0.035391 K70 26.0
2147 600048.XSHG 8.1683 1.2856 0.035235 K70 27.0
2715 600720.XSHG 8.1554 0.9302 0.035938 C30 28.0
565 002102.XSHE 8.1498 0.7802 0.030289 C27 29.0
2651 600649.XSHG 8.1240 0.7039 0.049801 K70 30.0
... ... ... ... ... ... ...
3064 601818.XSHG 6.3281 0.7967 0.045939 J66 69.0
163 000581.XSHE 6.2945 1.2637 0.068926 C36 70.0
2449 600393.XSHG 6.2107 0.8896 0.069307 K70 71.0
2614 600606.XSHG 6.2080 1.0711 0.043103 K70 72.0
265 000718.XSHE 6.1517 1.0429 0.035461 K70 73.0
404 000926.XSHE 6.1378 0.5635 0.032720 K70 74.0
3099 601988.XSHG 5.9936 0.7748 0.048619 J66 75.0
3003 601328.XSHG 5.9498 0.7355 0.049497 J66 76.0
2935 601009.XSHG 5.8820 1.0499 0.047196 J66 77.0
381 000898.XSHE 5.8328 0.8222 0.039523 C31 78.0
2165 600068.XSHG 5.8231 1.1424 0.043226 E48 79.0
2351 600279.XSHG 5.5936 0.7469 0.054545 G55 80.0
2410 600350.XSHG 5.5874 0.7485 0.040639 G54 81.0
2391 600325.XSHG 5.5034 1.0846 0.048240 K70 82.0
2975 601166.XSHG 5.4446 0.7883 0.041854 J66 83.0
53 000069.XSHE 5.1578 0.8957 0.053476 K70 84.0
2749 600755.XSHG 5.1164 1.0063 0.031397 F51 85.0
1141 002680.XSHE 5.0208 0.8758 0.122699 C27 86.0
609 002146.XSHE 4.9925 1.1959 0.057851 K70 87.0
2577 600567.XSHG 4.9160 1.1822 0.042625 C22 88.0
2433 600376.XSHG 4.8543 0.7787 0.093023 K70 89.0
2796 600808.XSHG 4.6497 1.1492 0.039192 C31 90.0
2440 600383.XSHG 4.5508 0.9644 0.065031 K70 91.0
99 000488.XSHE 4.3320 0.9892 0.057614 C22 92.0
42 000055.XSHE 4.2154 1.4189 0.038128 C33 93.0
338 000825.XSHE 4.0956 1.0213 0.050311 C31 94.0
306 000785.XSHE 3.9868 1.3978 0.030349 F52 95.0
2319 600240.XSHG 3.9346 0.5852 0.031847 K70 96.0
2704 600708.XSHG 2.9080 0.6737 0.046762 K70 97.0
12 000016.XSHE 1.5341 1.0370 0.047368 C39 98.0

98 rows × 6 columns

 

全部回复

0/140

量化课程

    移动端课程