Beispiel #1
0
 def calcDayDescriptor(self, stock_code: str, timepoint: str):
     try:
         period = self.params['N']
     except Exception as e:
         raise ("计算平均持股成本缺少回溯期数N")
     timepoint = datetime.strptime(timepoint, '%Y%m%d')
     priceInfo = fundamentalApi.quotes(
         asset_code=stock_code,
         starttime=None,
         endtime=timepoint - timedelta(days=1),
         period=period,
         fields=['Open', 'High', 'Low', 'Close', 'Tor_f'],
         freq='d',
         adj='hfq')
     if ((priceInfo['Tor_f'] > 0).sum() < period * 2 / 3
             or priceInfo.__len__() == 0):
         cgoValue = np.nan
     else:
         yesterdayClose = priceInfo['Close'].values[0]
         priceInfo['Tor_f'] = priceInfo['Tor_f'].clip(
             upper=1)  #换手率超过100%的视为100%
         priceInfo.sort_index(ascending=False, inplace=True)
         priceInfo['remianPart'] = (
             1 - priceInfo['Tor_f']).shift(1).fillna(1).cumprod()
         priceInfo['relativeWeight'] = priceInfo['remianPart'] * priceInfo[
             'Tor_f']
         priceInfo['priceWeight'] = priceInfo['relativeWeight'] / priceInfo[
             'relativeWeight'].sum()
         priceInfo['avgPrice'] = (priceInfo['High'] + priceInfo['Low'] +
                                  priceInfo['Open'] +
                                  priceInfo['Close']) / 4
         referencePrice = (priceInfo['priceWeight'] *
                           priceInfo['avgPrice']).sum()
         cgoValue = yesterdayClose / referencePrice - 1
     return cgoValue
Beispiel #2
0
 def calcDayDescriptor(self, stock_code: str, timepoint: str):
     timepoint_dt = datetime.strptime(timepoint, "%Y%m%d")
     try:
         t = self.params['t']  #计算量价背离所用回溯期数
         if (type(t) is not int or t < 1):
             raise Exception("回溯期t必须为大于1的整数!")
     except Exception as e:
         print("参数异常!")
         raise (e)
     priceInfo = fundamentalApi.quotes(
         asset_code=stock_code,
         starttime=None,
         endtime=timepoint_dt - timedelta(days=1),
         period=t,
         fields=['Open', 'High', 'Low', 'Close', 'Volume'],
         freq='d',
         adj='hfq')
     try:
         depart = 0.25 * (
             np.corrcoef(priceInfo['Open'], priceInfo['Volume']) +
             np.corrcoef(priceInfo['High'], priceInfo['Volume']) +
             np.corrcoef(priceInfo['Low'], priceInfo['Volume']) +
             np.corrcoef(priceInfo['Close'], priceInfo['Volume']))[0, 1]
     except:
         depart = np.nan
     return depart
Beispiel #3
0
 def calcDayDescriptor(self, stock_code: str, timepoint: str):
     timepoint_dt = datetime.strptime(timepoint, "%Y%m%d")
     try:
         n1, n2 = self.params['wait'], self.params['cum']  #间隔期,总长度
         if (type(n1) is not int or type(n2) is not int):
             raise Exception("间隔期wait、区间长度cum必须为非负整数!")
         if (n2 < 1):
             raise Exception("区间长度cum至少为1!")
     except Exception as e:
         print("参数异常!")
         raise (e)
     priceInfo = fundamentalApi.quotes(asset_code=stock_code,
                                       starttime=None,
                                       endtime=timepoint_dt -
                                       timedelta(days=1),
                                       period=n1 + n2,
                                       fields=['Open', 'Close'],
                                       freq='d',
                                       adj='hfq')
     try:
         momentum = priceInfo['Close'].values[n1] / priceInfo[
             'Open'].values[n1 + n2 - 1] - 1
     except:
         momentum = np.nan
     return momentum
    def __settleOrder(self,stockcode:str,dealprice:float,holdAmt:int,topModelPeriod:int):
        #被fire调用时执行
        #以股票交易价格作为已结模型的关闭仓位价格、新开模型的开仓价格,每只股票关闭时,尝试对OrderBook表、OrderBookDetail表登记实现损益
        #(这玩意不影响交易流程,但运行的时机和实际交易时机一致)

        #1.标记平仓行实际收益率real_ret
        #1.1 select出OrderBookDetail中所有待平仓行(所有已执行(即标记了开仓价及开仓后仓位),但未平仓,且指令源模型已到平仓时间的指令)
        #1.2 逐行循环,找出复权因子
        #1.3 计算实现平仓复权价与实现开仓复权价之间的收益率
        #1.4 记录收益率
        CalendarCount = fApi.trade_cal('SSE', self.MODEL_BEGIN_DATE, datetime.now().strftime('%Y%m%d'), '1').__len__()
        markCloseSql = 'select a.Id,a.AdjDt,a.stockcode,a.open_price from OrderBookDetail a ' \
                       'left join MultiFactorOptimizor b on a.Id=b.Id ' \
                       'where a.post_position is not null and a.real_ret is null' \
                       'and {CalendarCount}%b.ForcastPeriod=0 '.format(CalendarCount=CalendarCount)
        closeList = pd.read_sql_query(markCloseSql,fApi.conn)
        for k,v in closeList.iterrows():
            id,adjdt,stkcode,open_price = v
            openAdjFactor = fApi.quotes(stkcode,None,datetime.strptime(adjdt,'%Y%m%d'),1,'Adjfactor','d',None)['Adjfactor'].values[0]
            nowAdjFactor = fApi.quotes(stkcode,None,datetime.now()-timedelta(days=1),1,'Adjfactor','d',None)['Adjfactor'].values[0]
            openAdjPrice = open_price * openAdjFactor
            closeAdjPrice = dealprice * nowAdjFactor
            realRet = closeAdjPrice/openAdjPrice -1
            sql = 'replace into OrderBookDetail' \
              '(id, adjdt, stockcode, fore_position, adj_amount_plan, post_position_plan, post_position, open_price, exp_ret, real_ret)' \
              'select a.id, a.adjdt, a.stockcode, a.fore_position, a.adj_amount_plan, a.post_position_plan' \
              ', a.post_position, {dealprice}, a.exp_ret, {realRet}' \
              'from OrdeBookDetail a' \
              'where a.stockcode=\'{stockcode}\' and a.Id={Id} and a.AdjDt=\'{adjdt}\''.format(dealprice=dealprice,realRet=realRet,stockcode=stockcode,Id=id,adjdt=adjdt)
            fApi.conn.execute(sql)
        #2.标记开仓行的实际开仓价格和仓位(当前阶段,将现实仓位与计划仓位差异全归于顶层模型)
        #找出已下达但未执行(即未标记开仓价格和开仓后仓位)的指令,写入开仓价及开仓后仓位
        markOpenSql = 'replace into OrderBookDetail' \
              '(id, adjdt, stockcode, fore_position, adj_amount_plan, post_position_plan, post_position, open_price, exp_ret, real_ret)' \
              'select a.id, a.adjdt, a.stockcode, a.fore_position, a.adj_amount_plan, a.post_position_plan' \
              ', case when c.ForcastPeriod={topModelPeriod} then {holdAmt} else a.post_position_plan end' \
              ', {dealprice}, a.exp_ret, a.real_ret' \
              'from OrdeBookDetail a' \
              'left join OrderBook b on a.Id=b.Id and a.AdjDt=b.AdjDt' \
              'left join MultiFactorOptimozor c on a.Id=c.Id'\
              'where a.stockcode=\'{stockcode}\' and b.IsClosed=0 and a.post_position is null'.format(topModelPeriod=topModelPeriod,holdAmt=holdAmt,dealprice=dealprice,stockcode=stockcode)
        fApi.conn.execute(markOpenSql)
        fApi.conn.commit()
Beispiel #5
0
 def calcWeekDescriptor(self, stock_code: str, timepoint: str):
     try:
         period = self.params['period']
         indexCode = self.params['index']
     except Exception as e:
         raise ("计算股票beta缺少回溯期数period或参照指数index")
     timepoint = datetime.strptime(timepoint, '%Y%m%d')
     stockReturn = fundamentalApi.quotes(asset_code=stock_code,
                                         starttime=None,
                                         endtime=timepoint -
                                         timedelta(days=1),
                                         period=period,
                                         fields=['Close'],
                                         freq='d',
                                         adj='hfq')['Close'].pct_change()
     indexReturn = fundamentalApi.quotes(
         asset_code=indexCode,
         starttime=None,
         endtime=timepoint - timedelta(days=1),
         period=period,
         fields=['Close'],
         freq='d',
         adj=None,
         asset_type='index')['Close'].pct_change()
     mergeReturn = pd.DataFrame({
         'stock': stockReturn,
         'index': indexReturn
     })
     try:
         model = sm.OLS(mergeReturn['stock'].values.reshape(-1, 1),
                        sm.add_constant(mergeReturn['index'].values.reshape(
                            -1, 1)),
                        missing='drop')
         rst = model.fit()
         Beta = rst.params[1]
     except Exception as e:
         Beta = np.nan
     return Beta
Beispiel #6
0
 def calcWeekDescriptor(self, stock_code: str, timepoint: str):
     timepoint_dt = datetime.strptime(timepoint, "%Y%m%d")
     size_df = fundamentalApi.quotes(asset_code=stock_code,
                                     starttime=None,
                                     endtime=timepoint_dt -
                                     timedelta(days=1),
                                     period=1,
                                     fields='TotalMv',
                                     freq='d',
                                     adj=None)
     if (size_df.__len__() == 0):
         return np.nan
     else:
         return size_df.values[0][1]
 def makeOptimizeOrder(self):
     #从表MultiFactorOptimizor中获取今日激活运行的优化器,从基层到
     #高层(短周期)逐个执行;
     #每执行完一层改变一层当前对象base,并将新target插入OrderBook表;
     #执行前检查base周期是否可整除当前模型周期;若不可整除则跳过该层模型。
     #每日第二个执行
     rst = self.getActiveModelStackFromDB()
     num_of_models = rst.__len__()
     if(num_of_models==0):
         #本日非调仓日,无需操作
         print('本日无模型调仓!')
         return
     else:
         print('本日以下'+num_of_models.__str__()+'个模型调仓:')
         [print('{id}号模型,预测期{p}日'.format(id=str(id),p=str(forcastperiod))) for id,model,optmizor,forcastperiod in rst]
     stk_price = fApi.quotes(asset_code=None,starttime=None,endtime=datetime.now(), period=1, fields='Close', freq='day', adj=None)
     #todo 这里是以收盘价格近似次日开盘价格,若当日为除权登记日(即这两个价格会有较大差异时)时不可直接近似,需要对stk_price做除权处理
     stk_price.set_index('StockCode',inplace=True)
     cashrow = pd.DataFrame({'Close':1},index=['cash'])
     stk_price = stk_price.append(cashrow)
     stk_price = stk_price['Close']
     for id,model,optmizor,forcastperiod in rst:
         model:MultiFactor
         stk_return = model.forcastStkReturn()['e_ret']
         #multifactormodel.forcastStkCov需另写
         OptimizeOutcome = portfolioOptimizor(stk_return = stk_return
                                ,stk_price = stk_price
                                ,stk_cov=model.forcastStkCov()
                                ,stk_hold=self.base
                                ,feeRate=0.003
                                ,method=optmizor
                                ,gamma=0.1)
         target = OptimizeOutcome['after_adj_hold']['hold_quantity'].to_dict() #获取调整后持仓目标
         exp_ret = OptimizeOutcome['expRet']
         self.base = target
         #优化后,把新目标写入self.base、数据库OrderBook表、OrderBookDetail表
         sql = 'insert into OrderBook(Id,AdjDt,exp_ret,IsClosed) values(?,?,?,?)'
         fApi.conn.execute(sql,(id,datetime.now().strftime('%Y%m%d'),exp_ret,0))
         #再将目标插入OrderBookDetail表(内含现金行)
         for idx,row in OptimizeOutcome['after_adj_hold'].iterrows():
             stockcode = idx
             fore_position = row['remain_quantity']
             adj_amount_plan = row['trade_shares']
             post_position_plan = row['hold_quantity']
             stk_exp_ret = row['stk_return']
             stk_sql = 'insert into OrderBookDetail(Id,AdjDt,stockcode,fore_position,adj_amount_plan,post_position_plan,exp_ret)' \
                       'values (?,?,?,?,?,?,?)'
             fApi.conn.execute(stk_sql,(id,datetime.now().strftime('%Y%m%d'),stockcode,fore_position,adj_amount_plan,post_position_plan, stk_exp_ret))
         fApi.conn.commit()
Beispiel #8
0
 def calcDayDescriptor(self, stock_code: str, timepoint: str):
     timepoint_dt = datetime.strptime(timepoint, "%Y%m%d")
     priceInfo = fundamentalApi.quotes(asset_code=stock_code,
                                       starttime=None,
                                       endtime=timepoint_dt -
                                       timedelta(days=1),
                                       period=1,
                                       fields=['PB'],
                                       freq='d',
                                       adj=None)
     try:
         BTOP = 1 / priceInfo['PB'].values[0]
     except Exception as e:
         BTOP = np.nan
     return BTOP
 def calcDayDescriptor(self, stock_code: str, timepoint: str):
     timepoint_dt = datetime.strptime(timepoint, "%Y%m%d")
     try:
         n1 = self.params['n1']  #间隔期
         n2 = self.params['n2']  #总长度
         if (n2 < 1):
             raise ("n2至少为1!")
     except Exception as e:
         print("参数异常!")
         raise (e)
     priceInfo = fundamentalApi.quotes(asset_code=stock_code,
                                       starttime=None,
                                       endtime=timepoint_dt -
                                       timedelta(days=1),
                                       period=1,
                                       fields=['Open', 'Close'],
                                       freq='d',
                                       adj=None)
Beispiel #10
0
 def calcDayDescriptor(self, stock_code: str, timepoint: str):
     timepoint_dt = datetime.strptime(timepoint, "%Y%m%d")
     try:
         N = self.params['N']
     except Exception as e:
         print("params中必须输入计算非流动性回溯期N!")
         raise (e)
     priceInfo = fundamentalApi.quotes(asset_code=stock_code,
                                       starttime=None,
                                       endtime=timepoint_dt -
                                       timedelta(days=1),
                                       period=N,
                                       fields=['Open', 'Close', 'Amount'],
                                       freq='d',
                                       adj=None)
     priceInfo['dIlliq'] = abs((priceInfo['Close'] / priceInfo['Open'] -
                                1)) / priceInfo['Amount'] * pow(10, 8)
     Illiquidity = priceInfo['dIlliq'].mean()
     return Illiquidity
Beispiel #11
0
 def calcDayDescriptor(self, stock_code: str, timepoint: str):
     timepoint_dt = datetime.strptime(timepoint, "%Y%m%d")
     try:
         t = self.params['t']  #计算量价背离所用回溯期数
         if (type(t) is not int or t < 1):
             raise Exception("回溯期t必须为大于1的整数!")
     except Exception as e:
         print("参数异常!")
         raise (e)
     priceInfo = fundamentalApi.quotes(asset_code=stock_code,
                                       starttime=None,
                                       endtime=timepoint_dt -
                                       timedelta(days=1),
                                       period=t,
                                       fields=['Volume'],
                                       freq='d',
                                       adj='hfq')
     try:
         abnormalVol = priceInfo['Volume'][0] / np.mean(priceInfo['Volume'])
     except:
         abnormalVol = np.nan
     return abnormalVol