Ejemplo n.º 1
0
def get_market(code):
    """
    非常粗糙的通过代码获取交易市场的函数

    :param code:
    :return:
    """
    trans = {
        "USD": "US",
        "GBP": "UK",
        "HKD": "HK",
        "CNY": "CN",
        "CHF": "CH",
        "JPY": "JP",
        "EUR": "DE",
        "AUD": "AU",
        "INR": "IN",
        "SGD": "SG",
    }
    try:
        if code in market_info:
            return market_info[code]
        elif code.startswith("CNY/") or code.endswith("/CNY"):
            return "CM"  # china money 中间价市场标记
        elif code.startswith("HK") and code[2:].isdigit():
            return "HK"
        market = get_rt(code)["market"]
        if market is None:
            market = get_currency(code)
            market = trans.get(market, market)
    except (TypeError, AttributeError, ValueError, IndexError):
        market = "CN"
    return market
Ejemplo n.º 2
0
def get_currency(code):
    """
    通过代码获取计价货币的函数

    :param code:
    :return:
    """
    # 强制需要自带 cache,否则在回测 table 是,info 里没有的代码将很灾难。。。
    # only works for HKD JPY USD GBP CNY EUR, not very general when data source gets diverse more
    try:
        if code in currency_info:
            return currency_info[code]
        elif (code.startswith("F")
              or code.startswith("M")) and code[1:].isdigit():
            return "CNY"
        currency = get_rt(code)["currency"]
        if currency is None:
            currency = "CNY"
        elif currency == "JPY":
            currency = "100JPY"
    except (TypeError, AttributeError, ValueError):
        if code.startswith("FT-") and len(code.split(":")) > 2:
            currency = code.split(":")[-1]
        else:
            currency = "CNY"
    return currency
Ejemplo n.º 3
0
    def __init__(self, code, start=None, end=None):
        """

        :param code: str. 形式可以是 399971.XSHE 或者 SH000931
        :param start: Optional[str]. %Y-%m-%d, 估值历史计算的起始日。
        :param end: Dont use, only for debug
        """
        yesterday_str = (dt.datetime.now() -
                         dt.timedelta(days=1)).strftime("%Y-%m-%d")
        if len(code.split(".")) == 2:
            self.code = code
            self.scode = _convert_code(code)
        else:
            self.scode = code
            self.code = _inverse_convert_code(self.scode)
        if self.code in self.indexs:
            self.name = self.indexs[self.code][0]
            if not start:
                start = self.indexs[self.code][1]
        else:
            try:
                self.name = get_rt(self.scode)["name"]
            except:
                self.name = self.scode
            if not start:
                start = "2012-01-01"  # 可能会出问题,对应指数还未有数据
        self.start = start
        if not end:
            end = yesterday_str
        self.df = xu.get_daily("peb-" + self.scode, start=self.start, end=end)
        self.ratio = None
        self.title = "指数"
        self._gen_percentile()
Ejemplo n.º 4
0
def get_currency(code):
    """
    通过代码获取计价货币的函数

    :param code:
    :return:
    """
    # 强制需要自带 cache,否则在回测 table 时,info 里没有的代码将很灾难。。。
    # only works for HKD JPY USD GBP CNY EUR, not very general when data source gets diverse more
    try:
        if code in currency_info:
            return currency_info[code]
        elif (code.startswith("F")
              or code.startswith("M")) and code[1:].isdigit():
            return "CNY"
        elif code.startswith("FT-") and len(code.split(":")) > 2:
            # be careful! FT-ABC:IOM has no currency information!
            return code.split(":")[-1]
        elif code.startswith("HK") and code[2:].isdigit():
            return "HKD"
        currency = get_rt(code)["currency"]
        if currency is None:
            currency = "CNY"
        elif currency == "JPY":
            currency = "100JPY"
    except (TypeError, AttributeError, ValueError):
        logger.warning("set currency of %s as default CNY" % code)
        currency = "CNY"
    return currency
Ejemplo n.º 5
0
    def __init__(self, code, status, name=None):
        """

        :param code: str. 代码格式与 :func:`xalpha.universal.get_daily` 要求相同
        :param status: 记账单或 irecord 类。
        :param name: Optional[str]. 可提供标的名称。
        """
        self.code = code
        if isinstance(status, irecord):
            self.status = status.filter(code)
        else:
            self.status = status[status.code == code]
        # self.cftable = pd.DataFrame([], columns=["date", "cash", "share"])
        try:
            self.price = xu.get_daily(
                self.code,
                start=self.status.iloc[0]["date"].strftime("%Y-%m-%d"))
            self.price["netvalue"] = self.price["close"]
        except Exception as e:
            logger.warning("%s when trade trying to get daily price of %s" %
                           (e, self.code))
            self.price = None
        self._arrange()
        if not name:
            try:
                self.name = get_rt(code)["name"]
            except:
                self.name = code
        self.type_ = None
Ejemplo n.º 6
0
def get_market(code):
    """
    非常粗糙的通过代码获取交易市场的函数

    :param code:
    :return:
    """
    trans = {
        "USD": "US",
        "GBP": "UK",
        "HKD": "HK",
        "CNY": "CN",
        "CHF": "CH",
        "JPY": "JP",
        "EUR": "DE",
        "AUD": "AU",
        "INR": "IN",
        "SGD": "SG",
    }
    try:
        if code in market_info:
            return market_info[code]
        market = get_rt(code)["market"]
        if market is None:
            market = get_currency(code)
            market = trans.get(market, market)
    except (TypeError, AttributeError, ValueError, IndexError):
        market = "CN"
    return market
Ejemplo n.º 7
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
Ejemplo n.º 8
0
 def get_t1_rate(self, date=None, return_date=True):
     t1v, d = self.get_t1(date=date, return_date=True)
     cp = get_rt(self.code)["current"]
     r = (cp / t1v - 1) * 100
     if return_date:
         return r, d
     else:
         return r
Ejemplo n.º 9
0
 def get_t0_rate(self, percent=False, return_date=True):
     t0v, d = self.get_t0(percent=percent, return_date=True)
     cp = get_rt(self.code)["current"]
     r = (cp / t0v - 1) * 100
     if return_date:
         return r, d
     else:
         return r
Ejemplo n.º 10
0
 def get_t0_rate(self, percent=False, return_date=True):
     iopv = self.get_t0(percent=False, return_date=False)
     rtv = get_rt(self.code)["current"]
     r = (rtv / iopv - 1) * 100
     if return_date:
         return r, self.today.strftime("%Y-%m-%d")
     else:
         return r
Ejemplo n.º 11
0
    def get_t0(self, percent=False, return_date=True):
        """
        获取当日实时净值估计, 该接口每日凌晨到美股收盘(早晨),不保证自洽和可用

        :param percent: bool, default False。现在有两种实时的预测处理逻辑。若 percent 是 True,则将 t0dict 的
            每个持仓标的的今日涨跌幅进行估算,若为 False,则将标的现价和标的对应指数昨日收盘价的比例作为涨跌幅估算。不推荐使用 percent=True.
        :param return_date: bool, default True. return tuple, the second one is date in the format %Y%m%d
        :return: float
        """
        if not self.t0dict:
            raise ValueError("Please provide t0dict for prediction")
        t1value = self.get_t1(date=None, return_date=False)
        t = 0
        n = 0
        today_str = self.today.strftime("%Y%m%d")
        for k, v in self.t0dict.items():
            if not isinstance(v, dict):
                v = {"weight": v}
            if len(k.split("~")) > 1 and k.split("~")[-1].isdigit():
                # 为了持仓中可以同标的多次出现的 workaround
                k = k.split("~")[0]
            w = v["weight"]
            shift = v.get("time", None)
            base = v.get("base", None)
            t += w
            r = get_rt(
                k
            )  # k should support get_rt, investing pid doesn't support this!
            if percent:
                c = w / 100 * (1 + r["percent"] / 100)  # 直接取标的当日涨跌幅
            else:
                if k in futures_info and not base:
                    kf = futures_info[k]
                elif not base:
                    kf = k[:-8]  # k + "-futures"
                else:
                    kf = base
                try:
                    basev = self._base_value(kf, shift)
                except Exception as e:
                    kf = get_alt(kf)
                    if not kf:
                        raise e
                    else:
                        basev = self._base_value(kf, shift)
                c = w / 100 * r["current"] / basev
            currency_code = get_currency_code(k)
            if currency_code:
                c = c * daily_increment(currency_code, today_str)
                # TODO: 中间价未更新,但实时数据不检查问题也不大
            n += c
        n += (100 - t) / 100
        t0value = n * t1value
        self.t0_delta = n
        if not return_date:
            return t0value
        else:
            return t0value, self.today.strftime("%Y-%m-%d")
Ejemplo n.º 12
0
 def fluctuation(self):
     if not self.ratio:
         d = self.df.iloc[-1]["date"]
         oprice = xu.get_daily(code=self.scode,
                               end=d.strftime("%Y%m%d"),
                               prev=20).iloc[-1]["close"]
         nprice = get_rt(self.scode)["current"]
         self.ratio = nprice / oprice
     return self.ratio
Ejemplo n.º 13
0
 def __init__(self, code, start=None, end=None):
     self.code = code
     self.scode = code
     if not end:
         end = (dt.datetime.now() -
                dt.timedelta(days=1)).strftime("%Y-%m-%d")
     if not start:
         start = "2016-01-01"  # 基金历史通常比较短
     self.start = start
     self.df = xu.get_daily("peb-" + code, start=start, end=end)
     self.name = get_rt(code)["name"]
     self.title = "基金"
     self.ratio = None
     self._gen_percentile()
Ejemplo n.º 14
0
    def get_t1(self, return_date=True):
        """
        获取昨日基金净值

        :return:
        """
        if not self.t1value_cache:
            last_r = get_rt(self.fcode)
            last_value, last_date = last_r["current"], last_r["time"]
            self.t1value_cache = (last_value, last_date)
        if return_date:
            return self.t1value_cache
        else:
            return self.t1value_cache[0]
Ejemplo n.º 15
0
 def get_t0(self, return_date=True, percent=False):
     last_value, last_date = self.get_t1()
     last_date_obj = dt.datetime.strptime(last_date, "%Y-%m-%d")
     cday = last_onday(self.today)
     while last_date_obj < cday:  # 昨天净值数据还没更新
         # 是否存在部分部分基金可能有 gap?
         if cday.strftime("%Y-%m-%d") not in gap_info[self.fcode]:
             self.t1_type = "昨日未出"
             raise DateMismatch(
                 self.code,
                 reason="%s netvalue has not been updated to yesterday" %
                 self.code,
             )
         else:
             cday = last_onday(cday)
         # 经过这个没报错,就表示数据源是最新的
     if last_date_obj >= self.today:  # 今天数据已出,不需要再预测了
         print("no need to predict net value since it has been out for %s" %
               self.code)
         self.t1_type = "今日已出"
         if not return_date:
             return last_value
         else:
             return last_value, last_date
     t = 0
     n = 0
     today_str = self.today.strftime("%Y%m%d")
     for k, v in self.t0dict.items():
         w = v
         t += w
         r = get_rt(k)
         # k should support get_rt, investing pid doesn't support this!
         if percent:
             c = w / 100 * (1 + r["percent"] / 100)  # 直接取标的当日涨跌幅
         else:
             df = xu.get_daily(k)
             basev = df[df["date"] <= last_date].iloc[-1]["close"]
             c = w / 100 * r["current"] / basev
         currency_code = get_currency_code(k)
         if currency_code:
             c = c * daily_increment(currency_code, today_str)
         n += c
     n += (100 - t) / 100
     t0value = n * last_value
     self.t0_delta = n
     if not return_date:
         return t0value
     else:
         return t0value, self.today.strftime("%Y-%m-%d")
Ejemplo n.º 16
0
    def get_t2(self, return_date=True):
        """
        返回最新的已公布基金净值,注意这里严格按照最新公布,不一定是前两个交易日,可以更新,但更老会报错 DateMismatch

        :param return_date:
        :return: if return_date is True, tuple (value, %Y-%m-%d)
        """
        if not self.t2value_cache:
            last_r = get_rt(self.fcode)
            last_value, last_date = last_r["current"], last_r["time"]
            self.t2value_cache = (last_value, last_date)
        if return_date:
            return self.t2value_cache
        else:
            return self.t2value_cache[0]
Ejemplo n.º 17
0
    def __init__(self, code, status, name=None):
        """

        :param code: str. 代码格式与 :func:`xalpha.universal.get_daily` 要求相同
        :param status: 记账单或 irecord 类。
        :param name: Optional[str]. 可提供标的名称。
        """
        self.code = code
        if isinstance(status, irecord):
            self.status = status.filter(code)
        else:
            self.status = status[status.code == code]
        # self.cftable = pd.DataFrame([], columns=["date", "cash", "share"])
        self._arrange()
        if not name:
            try:
                self.name = get_rt(code)["name"]
            except:
                self.name = code
Ejemplo n.º 18
0
    def __init__(self, code, start=None, end=None):
        """

        :param code: 801180 申万行业指数
        :param start:
        :param end:
        """
        self.code = code
        self.scode = code
        if not end:
            end = (dt.datetime.now() -
                   dt.timedelta(days=1)).strftime("%Y-%m-%d")
        if not start:
            start = "2012-01-01"
        self.start = start
        self.df = xu.get_daily("peb-" + code, start=start, end=end)
        self.name = get_rt(code)["name"]
        self.ratio = 1
        self.title = "个股"
        self._gen_percentile()
Ejemplo n.º 19
0
    def process_byday(self, date):
        if not date:
            self.date_obj = dt.datetime.today()
        else:
            self.date_obj = dt.datetime.strptime(
                date.replace("-", "").replace("/", ""), "%Y%m%d")
        if not date:
            rt = get_rt(self.code)
            self.name = rt["name"]
            self.cbp = rt["current"]  # 转债价
            self.stockp = get_rt(self.scode)["current"]  # 股票价
        else:
            try:
                if not self.name:
                    rt = get_rt(self.code)
                    self.name = rt["name"]
            except:
                self.name = "unknown"
            df = xu.get_daily(self.code,
                              prev=100,
                              end=self.date_obj.strftime("%Y%m%d"))
            self.cbp = df.iloc[-1]["close"]
            df = xu.get_daily(self.scode,
                              prev=100,
                              end=self.date_obj.strftime("%Y%m%d"))
            self.stockp = df.iloc[-1]["close"]

        df = xu.get_daily(self.scode,
                          prev=360,
                          end=self.date_obj.strftime("%Y%m%d"))
        self.history_volatility = np.std(
            np.log(df["close"] / df.shift(1)["close"])) * np.sqrt(244)
        if not self.refvolatility:
            self.volatility = 0.17
            if self.rating in ["A", "A+", "AA-"]:
                self.volatility = 0.19
            elif self.rating in ["AA"]:
                self.volatility = 0.18
            if self.history_volatility < 0.25:
                self.volatility -= 0.01
            elif self.history_volatility > 0.65:
                self.volatility += 0.02
            elif self.history_volatility > 0.45:
                self.volatility += 0.01
        self.years = len(self.rlist) - 1
        syear = int(self.enddate.split("-")[0]) - self.years
        self.issuedate = str(syear) + self.enddate[4:]
        self.days = (dt.datetime.strptime(self.enddate, "%Y-%m-%d") -
                     self.date_obj).days
        if not self.refbondrate:
            ratestable = get_bond_rates(self.rating,
                                        self.date_obj.strftime("%Y-%m-%d"))
            if self.rating in ["A", "A+", "AA-"]:
                ## AA 到 AA- 似乎是利率跳高的一个坎
                cutoff = 2
            else:
                cutoff = 4
            if self.days / 365 > cutoff:
                # 过长久期的到期收益率,容易造成估值偏离,虽然理论上是对的
                # 考虑到国内可转债市场信用风险较低,不应过分低估低信用债的债券价值
                self.bondrate = (
                    ratestable[ratestable["year"] <= cutoff].iloc[-1]["rate"] /
                    100)
            else:
                self.bondrate = (ratestable[ratestable["year"] >= self.days /
                                            365].iloc[0]["rate"] / 100)
        if not self.refriskfreerate:
            ratestable = get_bond_rates("N",
                                        self.date_obj.strftime("%Y-%m-%d"))
            if self.days / 365 > 5:
                self.riskfreerate = (
                    ratestable[ratestable["year"] <= 5].iloc[-1]["rate"] / 100)
            else:
                self.riskfreerate = (
                    ratestable[ratestable["year"] >= self.days /
                               365].iloc[0]["rate"] / 100)