Пример #1
0
    def get_stock_holdings(
        self, year=None, season=None, date=yesterdayobj(), threhold=100
    ):
        """
        获取整个基金组合的底层股票持仓总和和细节,组合穿透

        :param year: 基于的基金季报年份
        :param season: 基于的基金季报季度
        :param date: 默认昨天
        :param threhold: 默认100。小于100元的底层股票将不在最后的结果中展示
        :return: pd.DataFrame column: name, code, value, ratio
        """
        d = {}
        if year is None or season is None:
            rd = convert_date(date) - pd.Timedelta(days=120)
            if not year:
                year = rd.year
            if not season:
                season = int((rd.month - 0.1) / 3) + 1
            logger.debug("use %s, %s for fund report" % (year, season))
        for f in self.fundtradeobj:
            if isinstance(f, itrade):
                if f.get_type() == "股票":
                    code = f.code
                elif f.get_type() == "场内基金":
                    code = f.code[2:]
                else:
                    continue
            else:
                code = f.code
            value = f.briefdailyreport(date).get("currentvalue", 0)
            if value > 0:
                if code.startswith("SH") or code.startswith("SZ"):
                    stock = code
                    d[stock] = d.get(stock, 0) + value
                elif code == "mf":
                    continue
                else:
                    df = get_fund_holdings(code, year, season)
                    if df is None:
                        continue

                    for _, row in df.iterrows():
                        stock = row["code"]
                        stock = ttjjcode(stock)
                        d[stock] = d.get(stock, 0) + row["ratio"] / 100 * value
                        # print("%s has %s contribution from %s" %(stock, row["ratio"] / 100 * value, f.name))

        l = []
        for code, value in sorted(d.items(), key=lambda item: -item[1]):
            if value >= threhold:
                try:
                    name = get_rt(code)["name"]
                except:
                    name = code
                l.append([name, code, value])
        fdf = pd.DataFrame(l, columns=["name", "code", "value"])
        fdf["ratio"] = fdf["value"] / fdf["value"].sum()
        return fdf
Пример #2
0
    def __init__(self,
                 code,
                 bondrate=None,
                 riskfreerate=None,
                 volatility=None,
                 name=None):
        """

        :param code: str. 转债代码,包含 SH 或 SZ 字头
        :param bondrate: Optional[float]. 评估所用的债券折现率,默认使用中证企业债对应信用评级对应久期的利率
        :param riskfreerate: Optioal[float]. 评估期权价值所用的无风险利率,默认使用国债对应久期的年利率。
        :param volatility: Optional[float]. 正股波动性百分点,默认在一个范围浮动加上历史波动率的小幅修正。
        :param name: str. 对于历史回测,可以直接提供 str,免得多次 get_rt 获取 name
        """
        # 应该注意到该模型除了当天外,其他时间估计会利用现在的转股价,对于以前下修过转股价的转债历史价值估计有问题

        self.code = code
        self.refbondrate = bondrate
        self.bondrate = self.refbondrate
        self.refriskfreerate = riskfreerate
        self.riskfreerate = self.refriskfreerate
        self.refvolatility = volatility
        self.volatility = self.refvolatility
        self.name = name

        r = rget("https://www.jisilu.cn/data/convert_bond_detail/" + code[2:])
        r.encoding = "utf-8"
        b = BeautifulSoup(r.text, "lxml")
        self.rlist = [
            float(re.search(r"[\D]*([\d]*.[\d]*)\%", s).group(1))
            for s in b.select("td[id=cpn_desc]")[0].string.split("、")
        ]
        self.rlist.append(float(b.select("td[id=redeem_price]")[0].string))
        self.rlist[-1] -= self.rlist[-2]  # 最后一年不含息返多少
        self.scode = (b.select("td[class=jisilu_nav]")
                      [0].contents[1].string.split("-")[1].strip())
        self.scode = ttjjcode(self.scode)  # 标准化股票代码
        self.zgj = float(b.select("td[id=convert_price]")[0].string)  # 转股价
        self.rating = b.select("td[id=rating_cd]")[0].string
        self.enddate = b.select("td[id=maturity_dt]")[0].string