def __init__(self, policylist, namelist=None, date=today()): self.warn = [] self.message = [] self.policylist = policylist if namelist is None: self.namelist = [i for i in range(len(policylist))] else: self.namelist = namelist assert len(self.policylist) == len(self.namelist) for i, policy in enumerate(policylist): row = policy.status[policy.status["date"] == date] if len(row) == 1: warn = ( policy.aim.name, policy.aim.code, row.iloc[0].loc[policy.aim.code], self.namelist[i], ) self.warn.append(warn) if warn[2] > 0: sug = "买入%s元" % warn[2] elif warn[2] < 0: ratio = -warn[2] / 0.005 * 100 share = (trade(fundinfo(warn[1]), policy.status).briefdailyreport().get( "currentshare", 0)) share = -warn[2] / 0.005 * share sug = "卖出%s%%的份额,也即%s份额" % (ratio, share) self.message.append("根据%s计划,建议%s,%s(%s)" % (warn[3], sug, warn[0], warn[1])) self.content = "\n".join(map(str, self.message))
def get_fund(code): if code[0] == "F": df = fundinfo(code[1:]).price elif code[0] == "M": df = mfundinfo(code[1:]).price df["close"] = df["netvalue"] return df[["date", "close"]]
def rfundinfo(code, label=1, fetch=False, save=False, path='', form='csv'): ''' give a fundinfo object with todays estimate netvalue at running time :param code: string of six digitals for funds :param fetch: boolean, when open the fetch option, info class will try fetching from local files first in the init :param save: boolean, when open the save option, info classes automatically save the class to files :param path: string, the file path prefix of IO :param form: string, the format of IO, options including: 'csv' :returns: the fundinfo object ''' fundobj = fundinfo(code, label=label, fetch=fetch, save=save, path=path, form=form) rt = rtdata(code) rtdate = dt.datetime.combine(rt.time, dt.time.min) rtvalue = rt.rtvalue if (rtdate - fundobj.price.iloc[-1].date).days > 0: fundobj.price = fundobj.price.append(pd.DataFrame( [[rtdate, rtvalue, fundobj.price.iloc[-1].totvalue, 0]], columns=['date', 'netvalue', 'totvalue', 'comment']), ignore_index=True) return fundobj
def __init__(self, *fundtradeobj, status=None, fetch=False, save=False, path="", form="csv"): if not fundtradeobj: # warning: not a very good way to automatic generate these fund obj # because there might be some funds use round_down for share calculation, ie, label=2 must be given # unless you are sure corresponding funds are added to the droplist fundtradeobj = [] for code in status.columns[1:]: try: fundtradeobj.append( trade( fundinfo(code, fetch=fetch, save=save, path=path, form=form), status, )) except FundTypeError: fundtradeobj.append( trade( mfundinfo(code, fetch=fetch, save=save, path=path, form=form), status, )) self.fundtradeobj = tuple(fundtradeobj) self.totcftable = self._mergecftb()
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
def __init__(self, *fundtradeobj, status=None, property=None, fetch=False, save=False, path="", form="csv"): if isinstance(status, record): if not property: property = getattr(status, "property", {}) status = status.status elif not property: property = {} if not fundtradeobj: # warning: not a very good way to automatic generate these fund obj # because there might be some funds use round_down for share calculation, ie, label=2 must be given # unless you are sure corresponding funds are added to the droplist fundtradeobj = [] for code in status.columns[1:]: # r1, d2, v4 p = r+d+v p = property.get(code, 0) round_label = p % 2 dividend_label = ((p - round_label) / 2) % 2 value_label = ((p - round_label - dividend_label) / 4) % 2 try: fundtradeobj.append( trade( fundinfo( code, round_label=round_label, dividend_label=dividend_label, fetch=fetch, save=save, path=path, form=form, ), status, )) except FundTypeError: fundtradeobj.append( trade( mfundinfo( code, round_label=round_label, value_label=value_label, fetch=fetch, save=save, path=path, form=form, ), status, )) self.fundtradeobj = tuple(fundtradeobj) self.totcftable = self._mergecftb()
def get_info(self, code): """ get the correct new info object based on Fcode :param code: :return: """ if code in self.infos: return self.infos[code] if code.startswith("F"): try: return fundinfo(code[1:]) except FundTypeError: return mfundinfo(code[1:]) elif code.startswith("M"): return mfundinfo(code[1:]) else: return vinfo( code, start=(self.start - pd.Timedelta(days=180)).strftime("%Y-%m-%d") )
def __init__(self, *fundtradeobj, status=None, istatus=None, property=None, fetch=False, save=False, path="", form="csv"): if isinstance(status, record): if not property: property = getattr(status, "property", {}) status = status.status elif not property: property = {} self.is_in = False if fundtradeobj: for t in fundtradeobj: if isinstance(t, itrade): self.is_in = True break else: fundtradeobj = [] # warning: not a very good way to automatic generate these fund obj # because there might be some funds use round_down for share calculation, ie, label=2 must be given # unless you are sure corresponding funds are added to the droplist fundcodelist = [f.code for f in fundtradeobj] if status is not None: for code in status.columns: if code == "date": continue # r1, d2, v4 p = r+d+v if code in fundcodelist: continue p = property.get(code, 0) round_label = p % 2 dividend_label = ((p - round_label) / 2) % 2 value_label = ((p - round_label - dividend_label) / 4) % 2 try: fundtradeobj.append( trade( fundinfo( code, round_label=round_label, dividend_label=dividend_label, fetch=fetch, save=save, path=path, form=form, ), status, )) except FundTypeError: fundtradeobj.append( trade( mfundinfo( code, round_label=round_label, value_label=value_label, fetch=fetch, save=save, path=path, form=form, ), status, )) if istatus is not None: self.is_in = True if isinstance(istatus, irecord): istatus = istatus.status for code in istatus.code.unique(): if code not in fundcodelist and not code.startswith("#"): fundtradeobj.append(itrade(code, istatus)) self.fundtradeobj = tuple(fundtradeobj) self.totcftable = self._mergecftb()