Ejemplo n.º 1
0
 def __init__(self, infoobj, start, end=yesterdaydash(), totmoney=100000):
     self.aim = infoobj
     self.totmoney = totmoney
     self.price = infoobj.price[(infoobj.price["date"] >= start)
                                & (infoobj.price["date"] <= end)]
     if len(self.price) == 0:
         self.start = convert_date(start)
         self.end = convert_date(end)
         self.status = pd.DataFrame(data={"date": [], self.aim.code: []})
     else:
         self.start = self.price.iloc[0].date
         self.end = self.price.iloc[-1].date
         datel = []
         actionl = []
         times = pd.date_range(self.start, self.end)
         for date in times:
             action = self.status_gen(date)
             if action > 0:
                 datel.append(date)
                 actionl.append(action)
             elif action < 0:
                 datel.append(date)
                 actionl.append(action * 0.005)
         df = pd.DataFrame(data={"date": datel, self.aim.code: actionl})
         self.status = df
Ejemplo n.º 2
0
def sell(remc, share, date):
    '''
    :returns: tuple, (sold rem, new rem)
        sold rem is the positions being sold while new rem is the positions being held
    '''
    rem = copy(remc)
    share = myround(share)
    date = convert_date(date)
    totposition = sum([pos[1] for pos in rem])  # the remaining shares
    if totposition == 0:
        return ([], [])
    if (date - rem[-1][0]).days < 0:
        raise Exception(_errmsg)
    if share > totposition:
        share = totposition  # not raise error when you sell more than you buy
    soldrem = []
    newrem = []
    for i, pos in enumerate(rem):
        if share > myround(sum([rem[j][1] for j in range(i + 1)])):
            soldrem.append(rem[i])
        elif share == myround(sum([rem[j][1] for j in range(i + 1)])):
            soldrem.append(rem[i])
        elif share < myround(sum([rem[j][1] for j in range(i + 1)])):
            if share > sum([rem[j][1] for j in range(i)]):
                soldrem.append([rem[i][0], share - sum([rem[j][1] for j in range(i)])])
                newrem.append([rem[i][0], sum([rem[j][1] for j in range(i + 1)]) - share])
            elif share <= sum([rem[j][1] for j in range(i)]):
                newrem.append(rem[i])
    return (soldrem, newrem)
Ejemplo n.º 3
0
    def __init__(self, *fundobjs, start=None):
        self.fundobjs = fundobjs
        self.totprice = (self.fundobjs[0].price[[
            "date", "netvalue"
        ]].rename(columns={"netvalue": fundobjs[0].code}))
        for fundobj in fundobjs[1:]:
            self.totprice = self.totprice.merge(
                fundobj.price[["date", "netvalue"
                               ]].rename(columns={"netvalue": fundobj.code}),
                on="date",
            )

        startdate = self.totprice.iloc[0].date
        if start is None:
            self.start = startdate
        else:
            start = convert_date(start)
            if start < startdate:
                raise Exception("Too early start date")
            else:
                self.start = start
                self.totprice = self.totprice[
                    self.totprice["date"] >= self.start]
        self.totprice = self.totprice.reset_index(drop=True)
        for col in self.totprice.columns:
            if col != "date":
                self.totprice[
                    col] = self.totprice[col] / self.totprice[col].iloc[0]
Ejemplo n.º 4
0
    def combsummary(self, date=yesterdayobj()):
        '''
        brief report table of every funds and the combination investment

        :param date: string or obj of date, show info of the date given
        :returns: empty dict if nothing is remaining that date
            dict of various data on the trade positions
        '''
        date = convert_date(date)
        columns = ['基金名称', '基金代码', '当日净值', '单位成本', '持有份额', '基金现值', '基金总申购', '历史最大占用',
                   '基金持有成本', '基金分红与赎回', '换手率', '基金收益总额', '投资收益率']
        summarydf = pd.DataFrame([], columns=columns)
        for fund in self.fundtradeobj:
            summarydf = summarydf.append(fund.dailyreport(date), ignore_index=True, sort=True)
        tname = '总计'
        tcode = 'total'
        tunitvalue = float('NaN')
        tunitcost = float('NaN')
        tholdshare = float('NaN')
        tcurrentvalue = summarydf['基金现值'].sum()
        tpurchase = summarydf['基金总申购'].sum()
        tbtnk = bottleneck(self.totcftable[self.totcftable['date'] <= date])
        tcost = summarydf['基金持有成本'].sum()
        toutput = summarydf['基金分红与赎回'].sum()
        tturnover = turnoverrate(self.totcftable[self.totcftable['date'] <= date], date)
        # 计算的是总系统作为整体和外界的换手率,而非系统各成分之间的换手率
        tearn = summarydf['基金收益总额'].sum()
        trate = round(tearn / tbtnk * 100, 4)
        trow = pd.DataFrame([[tname, tcode, tunitvalue, tunitcost, tholdshare,
                              tcurrentvalue, tpurchase, tbtnk, tcost, toutput, tturnover, tearn, trate]],
                            columns=columns)
        summarydf = summarydf.append(trow, ignore_index=True, sort=True)

        return summarydf[columns].sort_values(by="基金现值", ascending=False)
Ejemplo n.º 5
0
    def shuhui(self, share, date, rem):
        """
        give the cashout considering redemption rates as zero.
        if the date is not a trade date, then the purchase would happen on the next trade day, if the date is
        in the furture, then the trade date is taken as yesterday.

        :param share: float or int, number of shares to be sold
        :param date: string or object of date
        :returns: three elements tuple, the first is dateobj
            the second is a positive float for cashout,
            the third is a negative float for share decrease
        """
        date = convert_date(date)
        tots = sum([remitem[1] for remitem in rem if remitem[0] <= date])
        if share > tots:
            sh = tots
        else:
            sh = share
        partprice = self.price[self.price["date"] >= date]
        if len(partprice) == 0:
            row = self.price[self.price["date"] < date].iloc[-1]
        else:
            row = partprice.iloc[0]
        value = myround(sh * row.netvalue)
        return (row.date, value, -myround(sh))
Ejemplo n.º 6
0
    def dailyreport(self, date=yesterdayobj()):
        date = convert_date(date)
        partcftb = self.cftable[self.cftable["date"] <= date]
        value = self.get_netvalue(date)

        if len(partcftb) == 0:
            reportdict = {
                "基金名称": [self.name],
                "基金代码": [self.code],
                "当日净值": [value],
                "持有份额": [0],
                "基金现值": [0],
                "基金总申购": [0],
                "历史最大占用": [0],
                "基金分红与赎回": [0],
                "基金收益总额": [0],
            }
            df = pd.DataFrame(reportdict, columns=reportdict.keys())
            return df
        # totinput = myround(-sum(partcftb.loc[:,'cash']))
        totinput = myround(-sum(
            [row["cash"]
             for _, row in partcftb.iterrows() if row["cash"] < 0]))
        totoutput = myround(
            sum([
                row["cash"] for _, row in partcftb.iterrows()
                if row["cash"] > 0
            ]))

        currentshare = myround(sum(partcftb.loc[:, "share"]))
        currentcash = myround(currentshare * value)
        btnk = bottleneck(partcftb)
        turnover = turnoverrate(partcftb, date)
        ereturn = myround(currentcash + totoutput - totinput)
        if currentshare == 0:
            unitcost = 0
        else:
            unitcost = round((totinput - totoutput) / currentshare, 4)
        if btnk == 0:
            returnrate = 0
        else:
            returnrate = round((ereturn / btnk) * 100, 4)

        reportdict = {
            "基金名称": [self.name],
            "基金代码": [self.code],
            "当日净值": [value],
            "单位成本": [unitcost],
            "持有份额": [currentshare],
            "基金现值": [currentcash],
            "基金总申购": [totinput],
            "历史最大占用": [btnk],
            "基金持有成本": [totinput - totoutput],
            "基金分红与赎回": [totoutput],
            "换手率": [turnover],
            "基金收益总额": [ereturn],
            "投资收益率": [returnrate],
        }
        df = pd.DataFrame(reportdict, columns=reportdict.keys())
        return df
Ejemplo n.º 7
0
def xirrcal(cftable, trades, date, guess):
    '''
    calculate the xirr rate

    :param cftable: cftable (pd.Dateframe) with date and cash column
    :param trades: list [trade1, ...], every item is an trade object,
        whose shares would be sold out virtually
    :param date: string of date or datetime object,
        the date when virtually all holding positions being sold
    :param guess: floating number, a guess at the xirr rate solution to be used
        as a starting point for the numerical solution
    :returns: the IRR as a single floating number
    '''
    date = convert_date(date)
    partcftb = cftable[cftable['date'] <= date]
    if len(partcftb) == 0:
        return 0
    cashflow = [(row['date'], row['cash']) for i, row in partcftb.iterrows()]
    rede = 0
    for fund in trades:
        rede += fund.aim.shuhui(
            fund.briefdailyreport(date).get('currentshare', 0), date,
            fund.remtable[fund.remtable['date'] <= date].iloc[-1].rem)[1]
    cashflow.append((date, rede))
    return xirr(cashflow, guess)
Ejemplo n.º 8
0
def xirrcal(cftable, trades, date, guess=0.1):
    """
    calculate the xirr rate

    :param cftable: cftable (pd.Dateframe) with date and cash column
    :param trades: list [trade1, ...], every item is an trade object,
        whose shares would be sold out virtually
    :param date: string of date or datetime object,
        the date when virtually all holding positions being sold
    :param guess: floating number, a guess at the xirr rate solution to be used
        as a starting point for the numerical solution
    :returns: the IRR as a single floating number
    """
    date = convert_date(date)
    partcftb = cftable[cftable["date"] <= date]
    if len(partcftb) == 0:
        return 0
    cashflow = [(row["date"], row["cash"]) for i, row in partcftb.iterrows()]
    rede = 0
    for fund in trades:
        if not isinstance(fund, itrade):
            rede += fund.aim.shuhui(
                fund.briefdailyreport(date).get("currentshare", 0),
                date,
                fund.remtable[fund.remtable["date"] <= date].iloc[-1].rem,
            )[1]
        else:  # 场内交易
            pricedf = get_daily(fund.code, end=date.strftime("%Y%m%d"), prev=20)
            price = pricedf[pricedf.date <= date].iloc[-1]["close"]
            rede += fund.cftable.share.sum() * price
    cashflow.append((date, rede))
    return xirr(cashflow, guess)
Ejemplo n.º 9
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.º 10
0
 def unitvalue(self, date=yesterdayobj()):
     """
     :returns: float at unitvalue of the whole investment combination
     """
     date = convert_date(date)
     res = 0
     for fund in self.fundtradeobj:
         res += fund.briefdailyreport(date).get("currentvalue", 0)
     return res / self.totmoney
Ejemplo n.º 11
0
 def __init__(self, interest=0.0001, start="2012-01-01", value_label=0):
     self.interest = interest
     start = convert_date(start)
     self.start = start
     super().__init__("mf",
                      value_label=value_label,
                      fetch=False,
                      save=False,
                      path="nobackend")  # 永远不缓存 cashinfo
Ejemplo n.º 12
0
    def get_industry(self, date=yesterdayobj()):
        """
        获取基金组合持仓的行业占比信息,底层为非 A 股持仓的暂不支持

        :param date:
        :return: Dict
        """
        # TODO: hard coded 一个字典来合并一些二级行业
        d = {}
        date = convert_date(date)
        rd = date - pd.Timedelta(days=120)
        year = rd.year
        season = int((rd.month - 0.1) / 3) + 1
        for f in self.fundtradeobj:
            value = f.briefdailyreport(date).get("currentvalue", 0)
            if value > 0:
                if isinstance(f, itrade):
                    if f.get_type() == "股票":
                        industry = get_industry_fromxq(f.code).get(
                            "industryname", "")
                        if industry.strip():
                            d[industry] = d.get(industry, 0) + value
                        continue
                    elif f.get_type() in ["可转债", "债券", "货币基金"]:
                        # 现在简化实现可转债暂时不按正股记行业
                        continue
                    elif f.get_type() == "场内基金":
                        code = f.code[2:]
                    else:
                        continue
                else:
                    code = f.code
                if code == "mf":
                    continue
                if get_fund_type(code) == "货币基金":
                    continue
                ## 以下为持有股票的基金处理
                ## fundinfo 有点浪费,不过简化实现暂时如此
                fobj = fundinfo(code)
                industry_dict = fobj.get_industry_holdings(year=year,
                                                           season=season)
                if industry_dict is None:
                    continue
                ## 这里行业占比需要做个 scaling
                sv = sum([v for _, v in industry_dict.items()])
                if sv < 1.0:
                    # 只有极少数持仓存在行业信息
                    continue
                stock_ratio = fobj.get_portfolio_holdings(
                    date.strftime("%Y%m%d"))["stock_ratio"]
                scale = stock_ratio / sv
                print(scale)
                for k, v in industry_dict.items():
                    if k.strip():
                        d[k] = d.get(k, 0) + value * v / 100 * scale
        return d
Ejemplo n.º 13
0
 def __init__(self, start, end=None, totmoney=1000000, verbose=False, **kws):
     self.start = convert_date(start)
     self.verbose = verbose
     self.kws = kws
     self.totmoney = totmoney
     self.g = GlobalRegister()
     self.trades = {}  # codes: infoobj
     self.infos = {}  # codes: infoobj
     self.lastdates = {}  # codes: date
     if end is None:
         end = yesterdayobj()
     self.end = end
     self.sys = None
Ejemplo n.º 14
0
    def get_portfolio(self, date=yesterdayobj()):
        """
        获取基金组合底层资产大类配置的具体值

        :param date:
        :return: Dict[str, float]. stock,bond,cash 对应总值的字典
        """

        d = {"stock": 0, "bond": 0, "cash": 0}
        date = convert_date(date)
        for f in self.fundtradeobj:
            value = f.briefdailyreport(date).get("currentvalue", 0)
            if value > 0:
                if isinstance(f, itrade):
                    if f.get_type() == "股票":
                        d["stock"] += value
                        continue
                    elif f.get_type() in ["可转债", "债券"]:
                        d["bond"] += value
                        continue
                    elif f.get_type() == "货币基金":
                        d["cash"] += value
                        continue
                    elif f.get_type() == "场内基金":
                        code = f.code[2:]
                    else:
                        continue
                else:
                    code = f.code
                if code == "mf":
                    d["cash"] += value
                    continue
                if get_fund_type(code) == "货币基金":
                    d["cash"] += value
                    continue
                df = xu.get_daily("pt-F" + code, end=date.strftime("%Y%m%d"))
                if df is None or len(df) == 0:
                    logger.warning("empty portfolio info for %s" % code)
                row = df.iloc[-1]
                if row["bond_ratio"] + row["stock_ratio"] < 10:  # 联接基金
                    d["stock"] += (
                        (100 - row["bond_ratio"] - row["cash_ratio"]) * value / 100
                    )
                    d["bond"] += row["bond_ratio"] * value / 100
                    d["cash"] += row["cash_ratio"] * value / 100
                else:
                    d["stock"] += row["stock_ratio"] * value / 100
                    d["bond"] += row["bond_ratio"] * value / 100
                    d["cash"] += row["cash_ratio"] * value / 100
        return d
Ejemplo n.º 15
0
def trans(remc, coef, date):
    '''
    在基金份额折算时,将之前持有的仓位按现值折算,相当于前复权

    :param coef: the factor shown in comment column of fundinfo().price, but with positive value
    :param date: string in date form or datetime obj
    :returns: new rem after converting
    '''
    rem = copy(remc)
    date = convert_date(date)
    if len(rem) == 0:
        return []
    if (date - rem[-1][0]).days <= 0:
        raise Exception(_errmsg)
    newrem = [[item[0], myround(item[1] * coef)] for item in rem]
    return newrem
Ejemplo n.º 16
0
def turnoverrate(cftable, end=yesterdayobj()):
    """
    calculate the annualized turnoverrate

    :param cftable: pd.DataFrame of cftable
    :param end: str or obj of datetime for the end date of the estimation
    """
    if len(cftable) == 0:
        return 0
    end = convert_date(end)
    start = cftable.iloc[0].date
    tradeamount = sum(abs(cftable.loc[:, "cash"]))
    turnover = tradeamount / bottleneck(cftable) / 2.0
    if (end - start).days <= 0:
        return 0
    return turnover * 365 / (end - start).days
Ejemplo n.º 17
0
def xirrcal(cftable, trades, date, startdate=None, guess=0.01):
    """
    calculate the xirr rate

    :param cftable: cftable (pd.Dateframe) with date and cash column
    :param trades: list [trade1, ...], every item is an trade object,
        whose shares would be sold out virtually
    :param date: string of date or datetime object,
        the date when virtually all holding positions being sold
    :param guess: floating number, a guess at the xirr rate solution to be used
        as a starting point for the numerical solution
    :returns: the IRR as a single floating number
    """
    date = convert_date(date)
    partcftb = cftable[cftable["date"] <= date]
    if len(partcftb) == 0:
        return 0
    if not startdate:
        cashflow = [(row["date"], row["cash"])
                    for i, row in partcftb.iterrows()]
    else:
        if not isinstance(startdate, dt.datetime):
            startdate = dt.datetime.strptime(
                startdate.replace("-", "").replace("/", ""), "%Y%m%d")
        start_cash = 0
        for fund in trades:
            start_cash += fund.briefdailyreport(startdate).get(
                "currentvalue", 0)
        cashflow = [(startdate, -start_cash)]
        partcftb = partcftb[partcftb["date"] > startdate]
        cashflow.extend([(row["date"], row["cash"])
                         for i, row in partcftb.iterrows()])
    rede = 0
    for fund in trades:
        if not isinstance(fund, itrade):
            partremtb = fund.remtable[fund.remtable["date"] <= date]
            if len(partremtb) > 0:
                rem = partremtb.iloc[-1]["rem"]
            else:
                rem = []
            rede += fund.aim.shuhui(
                fund.briefdailyreport(date).get("currentshare", 0), date,
                rem)[1]
        else:  # 场内交易
            rede += fund.briefdailyreport(date).get("currentvalue", 0)
    cashflow.append((date, rede))
    return xirr(cashflow, guess)
Ejemplo n.º 18
0
 def _shuhui_by_share(self, share, date, rem):
     date = convert_date(date)
     tots = sum([remitem[1] for remitem in rem if remitem[0] <= date])
     if share > tots:
         sh = tots
     else:
         sh = share
     partprice = self.price[self.price["date"] >= date]
     if len(partprice) == 0:
         row = self.price[self.price["date"] < date].iloc[-1]
     else:
         row = partprice.iloc[0]
     value = myround(sh * row.netvalue)
     return (
         row.date,
         value,
         -myround(sh),
     )  # TODO: 这里 myround 是否也和 round_label 有关,有待考证
Ejemplo n.º 19
0
    def sellout(self, date=yesterdayobj(), ratio=1):
        '''
        Sell all the funds in the same ratio on certain day, it is a virtual process,
        so it can happen before the last action exsiting in the cftable, by sell out earlier,
        it means all actions behind vanish. The status table in self.status would be directly changed.

        :param date: string or datetime obj of the selling date
        :param ratio: float between 0 to 1, the ratio of selling for each funds
        '''
        date = convert_date(date)
        s = self.status[self.status['date'] <= date]
        row = []
        ratio = ratio * 0.005
        for term in s.columns:
            if term != 'date':
                row.append(-ratio)
            else:
                row.append(date)
        s = s.append(pd.DataFrame([row], columns=s.columns), ignore_index=True)
        self.status = s
Ejemplo n.º 20
0
    def briefdailyreport(self, date=yesterdayobj()):
        """
        quick summary of highly used attrs for trade

        :param date: string or object of datetime
        :returns: dict with several attrs: date, unitvalue, currentshare, currentvalue
        """
        date = convert_date(date)
        partcftb = self.cftable[self.cftable["date"] <= date]
        if len(partcftb) == 0:
            return {}

        unitvalue = self.get_netvalue(date)
        currentshare = myround(sum(partcftb.loc[:, "share"]))
        currentvalue = myround(currentshare * unitvalue)

        return {
            "date": date,
            "unitvalue": unitvalue,
            "currentshare": currentshare,
            "currentvalue": currentvalue,
        }
Ejemplo n.º 21
0
    def shuhui(self, share, date, rem):
        """
        give the cashout based on rem term considering redemption rates

        :returns: three elements tuple, the first is dateobj
            the second is a positive float for cashout,
            the third is a negative float for share decrease
        """
        # 		 value = myround(share*self.price[self.price['date']==date].iloc[0].netvalue)
        date = convert_date(date)
        partprice = self.price[self.price["date"] >= date]
        if len(partprice) == 0:
            row = self.price[self.price["date"] < date].iloc[-1]
        else:
            row = partprice.iloc[0]
        soldrem, _ = rm.sell(rem, share, row.date)
        value = 0
        sh = myround(sum([item[1] for item in soldrem]))
        for d, s in soldrem:
            value += myround(s * row.netvalue * (1 - self.feedecision(
                (row.date - d).days) * 1e-2))
        return (row.date, value, -sh)
Ejemplo n.º 22
0
def buy(remc, share, date):
    '''
    :param remc: array of two-elements arrays, eg [[pd.Timestamp(), 50],[pd.Timestamp(), 30]
        the first element in tuple is pandas.Timestamp object for date while the second
        element is positive float for remaining shares, tuples in rem MUST be time ordered.
    :param share: positive float, only 2 decimal is meaningful.
    :param date: string in the date form or datetime object
    :returns: new rem after the buying
    '''
    rem = copy(remc)
    share = myround(share)
    date = convert_date(date)
    if len(rem) == 0:
        return [[date, share]]
    elif (date - rem[-1][0]).days > 0:
        rem.append([date, share])
        return rem
    elif (date - rem[-1][0]).days == 0:
        rem[-1][1] = rem[-1][1] + share
        return rem
    else:
        raise Exception(_errmsg)
Ejemplo n.º 23
0
    def briefdailyreport(self, date=yesterdayobj()):
        '''
        quick summary of highly used attrs for trade

        :param date: string or object of datetime
        :returns: dict with several attrs: date, unitvalue, currentshare, currentvalue
        '''
        date = convert_date(date)
        partcftb = self.cftable[self.cftable['date'] <= date]
        if len(partcftb) == 0:
            return {}

        unitvalue = self.aim.price[
            self.aim.price['date'] <= date].iloc[-1].netvalue
        currentshare = myround(sum(partcftb.loc[:, 'share']))
        currentvalue = myround(currentshare * unitvalue)

        return {
            'date': date,
            'unitvalue': unitvalue,
            'currentshare': currentshare,
            'currentvalue': currentvalue
        }
Ejemplo n.º 24
0
    def dailyreport(self, date=yesterdayobj()):
        """
        breif report dict of certain date status on the fund investment

        :param date: string or obj of date, show info of the date given
        :returns: dict of various data on the trade positions
        """
        date = convert_date(date)
        partcftb = self.cftable[self.cftable["date"] <= date]
        print(partcftb)
        value = self.aim.price[
            self.aim.price["date"] <= date].iloc[-1].netvalue

        if len(partcftb) == 0:
            reportdict = {
                "基金名称": [self.aim.name],
                "基金代码": [self.aim.code],
                "当日净值": [value],
                "持有份额": [0],
                "基金现值": [0],
                "基金总申购": [0],
                "历史最大占用": [0],
                "基金分红与赎回": [0],
                "基金收益总额": [0],
            }
            df = pd.DataFrame(reportdict, columns=reportdict.keys())
            return df
        # totinput = myround(-sum(partcftb.loc[:,'cash']))
        totinput = myround(-sum(
            [row["cash"]
             for _, row in partcftb.iterrows() if row["cash"] < 0]))
        totoutput = myround(
            sum([
                row["cash"] for _, row in partcftb.iterrows()
                if row["cash"] > 0
            ]))

        currentshare = myround(sum(partcftb.loc[:, "share"]))
        currentcash = myround(currentshare * value)
        btnk = bottleneck(partcftb)
        turnover = turnoverrate(partcftb, date)
        ereturn = myround(currentcash + totoutput - totinput)
        if currentshare == 0:
            unitcost = 0
        else:
            unitcost = round((totinput - totoutput) / currentshare, 4)
        if btnk == 0:
            returnrate = 0
        else:
            returnrate = round((ereturn / btnk) * 100, 4)

        reportdict = {
            "基金名称": [self.aim.name],
            "基金代码": [self.aim.code],
            "当日净值": [value],
            "单位成本": [unitcost],
            "持有份额": [currentshare],
            "基金现值": [currentcash],
            "基金总申购": [totinput],
            "历史最大占用": [btnk],
            "基金持有成本": [totinput - totoutput],
            "基金分红与赎回": [totoutput],
            "换手率": [turnover],
            "基金收益总额": [ereturn],
            "投资收益率": [returnrate],
        }
        df = pd.DataFrame(reportdict, columns=reportdict.keys())
        return df
Ejemplo n.º 25
0
 def __init__(self, interest=0.0001, start='2012-01-01'):
     self.interest = interest
     start = convert_date(start)
     self.start = start
     super().__init__('mf')
Ejemplo n.º 26
0
    def combsummary(self, date=yesterdayobj()):
        """
        brief report table of every funds and the combination investment

        :param date: string or obj of date, show info of the date given
        :returns: empty dict if nothing is remaining that date
            dict of various data on the trade positions
        """
        date = convert_date(date)
        columns = [
            "基金名称",
            "基金代码",
            "当日净值",
            "单位成本",
            "持有份额",
            "基金现值",
            "基金总申购",
            "历史最大占用",
            "基金持有成本",
            "基金分红与赎回",
            "换手率",
            "基金收益总额",
            "投资收益率",
        ]
        summarydf = pd.DataFrame([], columns=columns)
        for fund in self.fundtradeobj:
            summarydf = summarydf.append(fund.dailyreport(date),
                                         ignore_index=True,
                                         sort=True)
        tname = "总计"
        tcode = "total"
        tunitvalue = float("NaN")
        tunitcost = float("NaN")
        tholdshare = float("NaN")
        tcurrentvalue = summarydf["基金现值"].sum()
        tpurchase = summarydf["基金总申购"].sum()
        tbtnk = bottleneck(self.totcftable[self.totcftable["date"] <= date])
        tcost = summarydf["基金持有成本"].sum()
        toutput = summarydf["基金分红与赎回"].sum()
        tturnover = turnoverrate(
            self.totcftable[self.totcftable["date"] <= date], date)
        # 计算的是总系统作为整体和外界的换手率,而非系统各成分之间的换手率
        tearn = summarydf["基金收益总额"].sum()
        trate = round(tearn / tbtnk * 100, 4)
        trow = pd.DataFrame(
            [[
                tname,
                tcode,
                tunitvalue,
                tunitcost,
                tholdshare,
                tcurrentvalue,
                tpurchase,
                tbtnk,
                tcost,
                toutput,
                tturnover,
                tearn,
                trate,
            ]],
            columns=columns,
        )
        summarydf = summarydf.append(trow, ignore_index=True, sort=True)

        return summarydf[columns].sort_values(by="基金现值", ascending=False)
Ejemplo n.º 27
0
    def dailyreport(self, date=yesterdayobj()):
        '''
        breif report dict of certain date status on the fund investment

        :param date: string or obj of date, show info of the date given
        :returns: dict of various data on the trade positions
        '''
        date = convert_date(date)
        partcftb = self.cftable[self.cftable['date'] <= date]
        value = self.aim.price[
            self.aim.price['date'] <= date].iloc[-1].netvalue

        if len(partcftb) == 0:
            reportdict = {
                '基金名称': [self.aim.name],
                '基金代码': [self.aim.code],
                '当日净值': [value],
                '持有份额': [0],
                '基金现值': [0],
                '基金总申购': [0],
                '历史最大占用': [0],
                '基金分红与赎回': [0],
                '基金收益总额': [0]
            }
            df = pd.DataFrame(reportdict, columns=reportdict.keys())
            return df
        # totinput = myround(-sum(partcftb.loc[:,'cash']))
        totinput = myround(-sum(
            [row['cash']
             for _, row in partcftb.iterrows() if row['cash'] < 0]))
        totoutput = myround(
            sum([
                row['cash'] for _, row in partcftb.iterrows()
                if row['cash'] > 0
            ]))

        currentshare = myround(sum(partcftb.loc[:, 'share']))
        currentcash = myround(currentshare * value)
        btnk = bottleneck(partcftb)
        turnover = turnoverrate(partcftb, date)
        ereturn = myround(currentcash + totoutput - totinput)
        if currentshare == 0:
            unitcost = 0
        else:
            unitcost = round((totinput - totoutput) / currentshare, 4)
        if btnk == 0:
            returnrate = 0
        else:
            returnrate = round((ereturn / btnk) * 100, 4)

        reportdict = {
            '基金名称': [self.aim.name],
            '基金代码': [self.aim.code],
            '当日净值': [value],
            '单位成本': [unitcost],
            '持有份额': [currentshare],
            '基金现值': [currentcash],
            '基金总申购': [totinput],
            '历史最大占用': [btnk],
            '基金持有成本': [totinput - totoutput],
            '基金分红与赎回': [totoutput],
            '换手率': [turnover],
            '基金收益总额': [ereturn],
            '投资收益率': [returnrate]
        }
        df = pd.DataFrame(reportdict, columns=reportdict.keys())
        return df
Ejemplo n.º 28
0
    def v_tradecost_ktest(
        self, unitcost=True, start=None, end=yesterdayobj(), rendered=True
    ):
        """
        visualization giving the average cost line together with netvalue line as well as buy and sell points

        :returns: pyecharts.line
        """
        # funddata = []
        # costdata = []

        pprice = self.price[self.price["date"] <= end]
        pcftable = self.cftable

        if start is not None:
            pprice = pprice[pprice["date"] >= start]
            pcftable = pcftable[pcftable["date"] >= start]
        # for _, row in pprice.iterrows():
        #     date = row["date"]
        #     funddata.append(row["netvalue"])
        #     if unitcost:
        #         cost = 0
        #         if (date - self.cftable.iloc[0].date).days >= 0:
        #             cost = self.unitcost(date)
        #         costdata.append(cost)
        #
        coords = []
        # pcftable = pcftable[abs(pcftable["cash"]) > threhold]
        # for i, r in pcftable.iterrows():
            # coords.append([r.date, pprice[pprice["date"] <= r.date].iloc[-1]["netvalue"]])
        def marker_factory(x, y):
            buy = pcftable[pcftable["date"] <= x].iloc[-1]["cash"]
            print("buy",buy)
            if buy < 0:
                color = "#ff7733"
            else:

                color = "#3366ff"
            size = (abs(buy) - lower) / (upper - lower) * 5 + 5
            print("size",size)
            return opts.MarkPointItem(
                coord=[x.date(), y],
                itemstyle_opts=opts.ItemStyleOpts(color=color),
            # this nested itemstyle_opts within MarkPointItem is only supported for pyechart>1.7.1
                symbol="circle",
                symbol_size=size,
            )

        def marker_factory3v(x, y):
            buy = pcftable[pcftable["date"] <= x].iloc[-1]["cash"]
            print("buy",buy)
            if buy < 0:
                color = "#ff7733"
            else:

                color = "#3366ff"
            # size = (abs(buy) - lower) / (upper - lower) * 5 + 5
            size = len(str(buy)) * 10
            print("size",size)
            return opts.MarkPointItem(
                value = -buy,
                coord=[x.date(), y],
                itemstyle_opts=opts.ItemStyleOpts(color=color),
            # this nested itemstyle_opts within MarkPointItem is only supported for pyechart>1.7.1
                # symbol="circle",
                symbol_size=size,
            )



        coords_cash = []
        # print("pcftable",pcftable)
        # print("pprice",pprice)
           #cash begin
        cashdata = []
        valuedata = []
        # partp = self.price[self.price["date"] >= self.cftable.iloc[0].date]
        # 多基金账单时起点可能非该基金持有起点
        # partp = partp[partp["date"] <= end]

        # valuedata = [
            # self.briefdailyreport(d).get("currentvalue", 0) for d in partp.date
            # self.briefdailyreport(d).get("currentvalue", 0) for d in pprice.date
        # ]
        # print(pprice.date)
        # print("begin to cal ccost")
        for d in pprice.date:
            ucost = self.unitcost(d)
            cshare = self.briefdailyreport(d).get("currentshare")
            if(ucost is None or cshare is None  ):
                valuedata.append(0)
                cashdata.append(0)
            else:
                cashdata.append(ucost*cshare)
                valuedata.append(self.briefdailyreport(d).get("currentvalue", 0))
        #     # self.unitcost(d)*self.briefdailyreport(d).get("currentshare")  for d in partp.date
        #     self.unitcost(d)*self.briefdailyreport(d).get("currentshare")  for d in pprice.date
        # ]
       #cash end


      # date = [d.date() for d in partp.date]
        date = [d.date() for d in pprice.date]
        date_dict = {}
        for i,d in enumerate(date):
            date_dict[convert_date(d)]=i
        # print("date_dict",date_dict)
        # print("date",date)
        # print("cashdata",cashdata)
        # pcftable = pcftable[abs(pcftable["cash"]) > threhold]
        # print("print offset")
        offset = pcftable["date"]
        # print("offset",offset)
        offset = offset[0]
        offsetdate = []
        coords_markvalue = []
        pos = 3
        for i, r in pcftable.iterrows():
            # print("i,r",i,r)
            # print("r.date",type(r.date.date()))
            # print("convert_date(r.date)",type(convert_date(r.date)))
            # print("date_dict[r.date]",date_dict[convert_date(r.date.date())])


            offset = r.date - offset

            valuecoords = valuedata[date_dict[convert_date(r.date.date())]]
            cashcoords = cashdata[date_dict[convert_date(r.date.date())]]
            distance = valuecoords - cashcoords
            if(pos == 3):
                coords_markvalue.append([r.date,cashcoords,offset])
                pos =0
            elif(pos == 0 ):
                coords_markvalue.append([r.date,cashcoords + distance/2,offset])
                pos = 1
            elif(pos == 1):
                coords_markvalue.append([r.date,valuecoords,offset])
                pos =2
            elif(pos ==2 ):
                coords_markvalue.append([r.date,cashcoords,offset])
                pos = 0



            # if(distance>2000):
                # pos = 1
                # coords_markvalue.append([r.date,cashcoords + distance/2,offset])
            # elif(distance<-2000):
                #coords_markvalue.append([r.date,valuecoords - distance/2,offset])
                # coords_markvalue.append([r.date,valuecoords - distance/2,offset])
            # else:
                #coords_markvalue.append([r.date,valuecoords,offset])
                # coords_markvalue.append([r.date,cashcoords,offset])

            coords_cash.append([r.date, cashdata[date_dict[convert_date(r.date.date())]],offset])
            coords.append([r.date,cashdata[date_dict[convert_date(r.date.date())]]])
            offsetdate.append(offset)
            offset = r.date
        # offsetdate[0] = pd.Timedelta(1,unit = "D")

        print("coords_cash",coords_cash)
        print("len(coords_cash)",len(coords_cash))
        # print("offsetdate",offsetdate)
        print("len(offsetdate)",len(offsetdate))


        upper = pcftable.cash.abs().max()
        lower = pcftable.cash.abs().min()
        if upper == lower:
            upper = 2 * lower + 1  # avoid zero in denominator
        global previous
        global direction
        previous = 0
        direction = 1


        def marker_factory1v(x, y,offsetday):
            offset = 0
            buy = pcftable[pcftable["date"] <= x].iloc[-1]["cash"]
            markvalue = 0
            ycoor = y
            global direction
            global previous
            print("previous before:",previous)

            # loc = (abs(buy) - lower) / (upper - lower) * 5000 + 5000
            loc = len(str(buy)) * 1000 + 1000
            if buy < 0:
                color = "#ff7733"
                markvalue = -buy
                if(offsetday < pd.Timedelta(7,unit = "D")):
                    offset = -100
                    ycoor = y + loc*previous*direction
                    previous = 1
                    direction =-direction
                else:
                    previous = 0

            else:
                color = "#3366ff"
                markvalue = -buy
                if(offsetday < pd.Timedelta(7,unit = "D")):
                    ycoor = y + loc*previous*direction
                    direction = -direction
                    previous = 1
                else:
                    previous = 0
            print("previous after",previous)
            # size = (abs(buy) - lower) / (upper - lower) * 50 + 50
            size = len(str(buy)) * 10
            return opts.MarkPointItem(name="test",
                coord=[x.date(), ycoor],
                value = -buy,
                itemstyle_opts=opts.ItemStyleOpts(color=color),
                # this nested itemstyle_opts within MarkPointItem is only supported for pyechart>1.7.1
                # symbol="circle",
                # symbol="rectangle",
                symbol_size=size,
            )
        def marker_factory2v(x, y,offsetday):
            offset = 0
            buy = pcftable[pcftable["date"] <= x].iloc[-1]["cash"]
            markvalue = 0
            ycoor = y
            global direction
            global previous
            print("previous before:",previous)
            print("offsetday",offsetday)
            print("day",x.date())

            # loc = (abs(buy) - lower) / (upper - lower) * 5000 + 5000
            loc = len(str(buy)) * 100
            if buy < 0:
                color = "#ff7733"
                markvalue = -buy
                if(offsetday < pd.Timedelta(5,unit = "D")):
                    offset = -100
                    #ycoor = y + loc*previous*direction
                    ycoor = y +loc*previous*direction
                    previous = 1
                    direction =-direction
                else:
                    previous = 0

            else:
                color = "#3366ff"
                markvalue = -buy
                if(offsetday < pd.Timedelta(5,unit = "D")):
                    #ycoor = y + loc*previous*direction
                    ycoor = y + loc*previous*direction
                    direction = -direction
                    previous = 1
                else:
                    previous = 0
            print("previous after",previous)
            # size = (abs(buy) - lower) / (upper - lower) * 50 + 50
            size = len(str(round(-buy))) * 12
            return opts.MarkPointItem(name="test",
                coord=[x.date(), ycoor],
                value = -round(buy),
                itemstyle_opts=opts.ItemStyleOpts(color=color),
                # this nested itemstyle_opts within MarkPointItem is only supported for pyechart>1.7.1
                # symbol="circle",
                # symbol="rectangle",
                symbol_size=size,
            )


        # print("getting cashdata,pprice",pprice.date)


            # print("2cashdata",cashdata)
        # print("funddata",funddata)
        print("len(2chashdata)",len(cashdata))
        # print("funddata",len(funddata))
        # print("valuedata",valuedata)
        print("len(valuedata)",len(valuedata))

        line = Line()

        #line.add_xaxis([d.date() for d in pprice.date])
        line.add_xaxis(date)

        line.add_yaxis(
                       series_name="持仓总值1",
                       y_axis=valuedata,
                       # is_symbol_show=False,
                       # )

            # y_axis=funddata,
            is_symbol_show=False,
            markpoint_opts=opts.MarkPointOpts(
                data=[marker_factory2v(*c) for c in coords_markvalue],
            ),
        )
        line.extend_axis(
                         yaxis = opts.AxisOpts(
                                axislabel_opts = opts.LabelOpts(formatter="{value}%",)))
        print("xianjinzhi")
        line.add_yaxis(
            series_name="现金值",
            y_axis=cashdata,
            is_symbol_show=False,
            markpoint_opts=opts.MarkPointOpts(
                # data=[marker_factory(*c) for c in coords_cash],
                data=[marker_factory(*c) for c in coords],
                # symbol = "circle",
                # symbol_size =size,
            ),
        )

        def tooltip_factory(coords):
            for x,y in coords:
                return opts.TooltipOpts(
                is_show=True,
                trigger="axis",
                trigger_on="mousemove",
                axis_pointer_type="cross",
                formatter = str(y)
            )

        line.set_global_opts(
            datazoom_opts=[
                opts.DataZoomOpts(
                    is_show=True, type_="slider", range_start=50, range_end=100
                ),
                opts.DataZoomOpts(
                    is_show=True,
                    type_="slider",
                    orient="vertical",
                    range_start=50,
                    range_end=100,
                ),
            ],
            tooltip_opts=opts.TooltipOpts(
                is_show=True,
                trigger="axis",
                # trigger_on="mousemove",
                trigger_on="click",
                axis_pointer_type="cross",
                # formatter = [tooltip_factory(*c) for c in coords]
                formatter = JsCode(
                    """function(params){
                    if(params.dataIndex){
                    return params.dataIndex
                    }
                    else{
                    return params
                    }
                }
                    """
                )
            ),
            # tooltip_opts=tooltip_factory(coords)
            # tooltip_opts=tooltip_factory(coords)
        )

        if rendered:
            return line.render_notebook()
Ejemplo n.º 29
0
 def __init__(self, interest=0.0001, start="2012-01-01"):
     self.interest = interest
     start = convert_date(start)
     self.start = start
     super().__init__("mf")
Ejemplo n.º 30
0
    def v_xirrate(self,start_date, end_date=yesterdayobj()):
        """
        graph of the xirate of the over all investment

        :param date: string or obj of date, show info of the date given
        :returns:
        """
        start_date = convert_date(start_date)
        end_date = convert_date(end_date)
        columns = [
            "基金名称",
            "基金代码",
            "当日净值",
            "单位成本",
            "持有份额",#changed to date
            "基金现值",
            "基金总申购",
            "历史最大占用",
            "基金持有成本",
            "基金分红与赎回",
            "换手率",
            "基金收益总额",
            "投资收益率",
        ]
        columns_tot = [
            "基金名称",
            "基金代码",
            "当日净值",
            "单位成本",
            "持有份额",#changed to date
            "基金现值",
            "基金总申购",
            "历史最大占用",
            "基金持有成本",
            "基金分红与赎回",
            "换手率",
            "基金收益总额",
            "投资收益率",
        ]
        tsummarydf = pd.DataFrame([],columns=columns)
        for date in pd.date_range(start_date,end_date):
            summarydf = pd.DataFrame([], columns=columns)
            for fund in self.fundtradeobj:
                summarydf = summarydf.append(
                    fund.dailyreport(date), ignore_index=True, sort=True
                )
            tname = "总计"
            tcode = "total"
            tunitvalue = float("NaN")
            tunitcost = float("NaN")
            tholdshare = date
            tcurrentvalue = summarydf["基金现值"].sum()
            tpurchase = summarydf["基金总申购"].sum()
            tbtnk = bottleneck(self.totcftable[self.totcftable["date"] <= date])
            tcost = summarydf["基金持有成本"].sum()
            toutput = summarydf["基金分红与赎回"].sum()
            tturnover = turnoverrate(self.totcftable[self.totcftable["date"] <= date], date)
            # 计算的是总系统作为整体和外界的换手率,而非系统各成分之间的换手率
            tearn = summarydf["基金收益总额"].sum()
            trate = round(tearn / tbtnk * 100, 4)
            trow = pd.DataFrame(
                [
                    [
                        tname,
                        tcode,
                        tunitvalue,
                        tunitcost,
                        tholdshare,
                        tcurrentvalue,
                        tpurchase,
                        tbtnk,
                        tcost,
                        toutput,
                        tturnover,
                        tearn,
                        trate,
                    ]
                ],
                columns=columns
            )
            # summarydf = summarydf.append(trow, ignore_index=True, sort=True)
            tsummarydf = tsummarydf.append(trow, ignore_index=True, sort=True)

        return tsummarydf[columns].sort_values(by="持有份额", ascending=False)