Example #1
0
 def capm(cls, goods, kline):
     """
     计算Alpha, Beta这两个指标,由于这两个指标的计算比较复杂,
     所以在回测过程中不主动计算他们,当用户需要计算这两个指标
     时,把verify_XXX函数返回的goods传递给capm就可以计算得出
     Alpha, Beta.
     :param kline:
     :param goods:
     :return:
     """
     try:
         kline = 'index_' + re.search('(min\d+)|(day)', kline, re.I).group()
         index_data = cls.index_profit(sd=goods.open_date.min(), ed=goods.close_date.max(), kline=kline)
         index_profit = list()
         for i, r in goods.iterrows():
             idp = index_data[(index_data.date > r['open_date']) & (index_data.date <= r['close_date'])]
             index_profit.append(idp.profit.sum())
         goods['index_profit'] = index_profit
         menu = goods.copy(deep=True)
         menu['MC'] = menu.profit * menu.Rr  # 边际贡献
         if re.search('min', kline, re.I) is not None:
             menu['close_date'] = menu.close_date.dt.strftime('%Y-%m-%d')
             menu['close_date'] = pd.to_datetime(menu.close_date, format='%Y-%m-%d')
         menu = menu.groupby(['close_date'], as_index=False).agg({'MC': 'sum', 'index_profit': 'mean'})
         menu = menu.rename(columns={'MC': 'profit', 'close_date': 'date'})
         Alpha, Beta = fi.CAPM(menu.profit.tolist(), menu.index_profit.tolist())
         return Alpha, Beta, menu
     except Exception as e:
         ExceptionInfo(e)
         return 'N/A', 'N/A', None
Example #2
0
    def accept(self, callback):
        
        try:
            BroadCast.skt.bind(('', self.PORT))
            print(fontcolor.F_GREEN + '-' * 80)
            print('Listening for broadcast at ', BroadCast.skt.getsockname())
            print('Datetime:%s' % dt.datetime.now())
            print('-' * 80 + fontcolor.END)
        except Exception as e:
            print(fontcolor.F_RED + '-' * 80)
            print('Broadcast system failed to start. error '
                  'code : ' + str(e))
            print('-' * 80 + fontcolor.END)
            sys.exit()
        # print('Listening for broadcast at ', skt.getsockname())

        while True:
            if BroadCast.status is not True:
                break
            print('Waiting for a new broadcast...')
            data, address = BroadCast.skt.recvfrom(65535)
            print(fontcolor.F_GREEN + '-' * 80)
            print('Received broadcast from:{0}, datetime: {1}'.format(
                address, dt.datetime.now()))
            print('-' * 80 + fontcolor.END)
            rec = data.decode('utf-8')
            try:
                callback(rec)
            except Exception as e:
                ExceptionInfo(e)
        BroadCast.status = True
Example #3
0
 def param_optimization(cls, param_table, on='day', order_close=None):
     """
     暴力参数求解
     :param param_table:包含max_pst_vol,max_pst_days,stop_get,stop_loss交易参数组合
     的参数表,这是一个df
     :param on:何种级别的回测
     :return:
     """
     if on not in ('day', 'min'):
         raise ValueError('this "on" must in (day, min)')
     rls = list()
     for i, r in param_table.iterrows():
         try:
             # p = dict(max_pst_vol=r.max_pst_vol, max_pst_days=r.max_pst_days, stop_get=r.stop_get, stop_loss=r.stop_loss)
             cls.modelparammodify(max_pst_vol=r.max_pst_vol,
                                  max_pst_days=r.max_pst_days,
                                  stop_get=r.stop_get,
                                  stop_loss=r.stop_loss)
             dit, mus, tdr = cls.verify_day(
                 order_close) if on == 'day' else cls.verify_min(
                     order_close)
             rp = dict(dit, **r)
         except Exception as e:
             ExceptionInfo(e)
             rp = dict(r)
         finally:
             rls.append(rp)
     rls = pd.DataFrame(rls)
     return rls
Example #4
0
 def usa_order_close(cls, signal):
     """
     适用于美股融资融券当日冲销账户(要成为这一类用户,账户余额必须大于$25,000),
     执行T+0交易规则,不受交割制度困扰(T+3),但可能会受到资金规模困扰,这与券商相关,
     外汇也适用于这种类型的平仓
     :param signal:
     :return:
     """
     try:
         code = signal['code']
         od = signal['open_date']
         open_price = signal['open_price']
         mark = signal['type']
         s = od
         for d in range(0, 12, 1):
             if cls.ntf:
                 # 持有时间按交易日计算
                 # 可能存在不合理的情况,因为目前我们不确定美股市场休市的安排
                 e = td.trade_period(od, days=d + cls.model_param['max_pst_days'], holidays=[])
             else:
                 e = od + datetime.timedelta(days=d + cls.model_param['max_pst_days'])  # 持有时间按自然日计算
             e = e + datetime.timedelta(minutes=cls.model_param['max_pst_mins'])
             try:
                 data = cls.func(code, s, e, cls.kline)
             except Exception:
                 raise TypeError('User-defined function raise a Exception')
             if len(data):
                 data = data[(data.date >= s) & (data.date <= e)]
                 if len(data):
                     return cls.close(data, mark, open_price)
         return e, 1, 404, 0
     except Exception as ep:
         ExceptionInfo(ep)
Example #5
0
 def finally_datetime(cls, date, max_pst_days=1, bsi=False):
     """
     根据开仓时间和最长持有时间计算买出时间,适用于中国A股股票
     :param bsi: False表示按自然日计算持有的时间, True表示按交易日计算
     :param date:
     :param max_pst_days:
     :return:
     """
     try:
         time = dt.timedelta(hours=14, minutes=55)
         start = dt.datetime(date.year, date.month, date.day)
         if bsi:
             end = trading.trade_period(start, max_pst_days)
             return end + time
         else:
             end = start + dt.timedelta(days=max_pst_days)
             if trading.is_trade_day(end):
                 return end + time
             else:  # end 不是交易日
                 if trading.trade_days(start, end) > 0:  # 向前推算
                     for i in range(1, max_pst_days, 1):
                         end = end - dt.timedelta(days=1)
                         if trading.is_trade_day(end):
                             return end + time
                 else:  # 向后推算
                     for i in range(1, 11, 1):
                         end = start + dt.timedelta(days=i)
                         if trading.is_trade_day(end):
                             return end + time
             return date
     except Exception as e:
         ExceptionInfo(e)
         return date
Example #6
0
 def unreplenishment(cls, data, method='local'):
     """
     将XDXR_day复权后的价格更新至现价
     :param method:获取现价的方法:net表示从网络接口获取最新价作为现价
      local表示从本地数据库获取。
      目前反复权操作指针对中国A股XDXR_day 表,将其close-->现价
     :param data:
     :return:
     """
     try:
         if method == 'net':
             real_data = rd.get_stocks_data(list(data.stock_code))
             data.drop('close', axis=1, inplace=True)
             data = pd.merge(data,
                             real_data.loc[:, ['stock_code', 'price']],
                             on='stock_code')
             data.rename(columns={'price': 'close'}, inplace=True)
         if method == 'local':
             data['close'] = data.apply(lambda r: kd.read_one(
                 r['stock_code'], r['date'], 'kline_day')['close'],
                                        axis=1)
         return data
     except Exception as e:
         ExceptionInfo(e)
         return pd.DataFrame()
Example #7
0
 def real_profit(cls, data, market='ZH'):
     """
     计算实时收益
     :param market:
     :param data:信号片集,来自于signals,orders...表
     :return:
     """
     try:
         from Calf.data import RealData as rd
         if market == 'ZH':
             real_data = rd.get_stocks_data(list(data.stock_code.unique()))
         elif market == 'US':
             real_data = rd.usa_stock_data(list(data.stock_code.unique()))
         elif market == 'HK':
             real_data = rd.hk_stock_data(list(data.stock_code.unique()))
         else:
             raise ValueError('Calf current only support (ZH, US, HK)')
         if real_data is None:
             return pd.DataFrame()
         data = pd.merge(data, real_data, on=['stock_code'])
         data['price'] = data.price.astype('float')  # 实时价格
         data['profit'] = (data.price - data.open_price) / data.open_price
         data.fillna(0, inplace=True)
         data = data[data.price > 0]  # 避免数据没读到,而返回0
         return data
     except Exception as e:
         ExceptionInfo(e)
         return pd.DataFrame()
Example #8
0
 def simple_close(cls, signal):
     """
     平仓的信息直接由回测的历史信号给出,这样我们在执行历史信号平仓函数的时候可以直接在
     历史信号中找到那个关于平仓的信息。当你想要执行这种类型的回测时,所给出的signal则
     必须包含额外的close_date,close_price这两个字段
     :param signal:
     :return:
     """
     try:
         # code = signal['code']
         close_date = signal['close_date']
         close_price = signal['close_price']
         open_price = signal['open_price']
         pf = close_price / open_price
         # d = cls.kd.read_one(code, close_date, cls.kline)
         # if close_price < d['close']:
         #     # 以卖出指导价卖出
         #     pf = close_price / open_price
         #     return close_date, pf, 0
         # else:
         #     pf = d['close'] / open_price
         #     return close_date, pf, 0
         return close_date, pf, 0, close_date
         pass
     except Exception as e:
         ExceptionInfo(e)
Example #9
0
 def action_end(args):
     print(fontcolor.F_GREEN + '-' * 80)
     print('Calf-Note:end task running on ',
           dt.datetime.now(tz=tz))
     print('-' * 80 + fontcolor.END)
     try:
         action.end(args=args)
     except Exception as ep:
         ExceptionInfo(ep)
Example #10
0
 def open_kline_update_log(cls):
     try:
         with open(project_dir + '/Calf/kline_update_log.json',
                   encoding='utf-8') as file:
             content = json.load(file)
         return content
     except Exception as e:
         ExceptionInfo(e)
         return {}
Example #11
0
 def broading(self, message):
     try:
         network = '<broadcast>'
         BroadCast.skt.sendto(message.encode('utf-8'), (network, self.PORT))
         print(fontcolor.F_GREEN + '-' * 80)
         print('Broadcast success, datetime: ', dt.datetime.now())
         print('-' * 80 + fontcolor.END)
     except Exception as e:
         ExceptionInfo(e)
Example #12
0
    def similar_amount(cls, goods, kline, gap=5):
        """
        计算交易信号发生后gap分钟内发生的交易额,适用于A股
        :param goods:
        :return:
        """
        try:
            goods['sa'] = np.nan
            goods['sl'] = np.nan
            goods['sh'] = np.nan
            for i, g in goods.iterrows():
                sd = datetime.datetime(g.open_date.year, g.open_date.month,
                                       g.open_date.day)
                if g.open_date.hour == 0 and g.open_date.minute == 0:
                    # 日线,特殊处理
                    tme = {'$in': [1455, 1500]}
                else:
                    # 日内
                    if g.open_date.hour == 15:
                        # 日内收盘时的信号
                        tme = 1500
                    elif g.open_date.hour == 11 and g.open_date.minute == 30:
                        # 日内上午收盘时的信号
                        tme = 1305
                    else:
                        tme = (g.open_date.minute + gap) // 5
                        dt = sd + datetime.timedelta(hours=g.open_date.hour,
                                                     minutes=tme * 5)
                        tme = dt.hour * 100 + dt.minute * 5
                d = cls.kd.read_data(code=g.code,
                                     start_date=sd,
                                     end_date=sd,
                                     kline=kline,
                                     time=tme)
                if len(d):
                    sa = d.amount.sum()
                    sl = d.low.min()
                    sh = d.high.max()
                else:
                    sa, sl, sh = np.nan, np.nan, np.nan

                goods.at[i, ['sa', 'sl', 'sh']] = sa, sl, sh
            goods['pv'] = pd.eval('(goods.sh - goods.sl) / goods.open_price')
            menu = goods.copy(deep=True)
            menu.dropna(axis=0, inplace=True)
            if len(menu):
                menu['date'] = menu.close_date.dt.strftime('%Y-%m-%d')
                menu['date'] = pd.to_datetime(menu.date, format='%Y-%m-%d')
                menu = menu.groupby(['date'], as_index=False).agg({
                    'sa': 'sum',
                    'pv': 'mean'
                })
            return goods, menu
            pass
        except Exception as e:
            ExceptionInfo(e)
Example #13
0
def sound_notice(sound_name):
    """
    以多线程的方式播放一段音频文件
    :param sound_name:
    :return:
    """
    try:
        t = threading.Thread(target=play_music, args=(sound_name,))
        return t
    except Exception as e:
        ExceptionInfo(e)
Example #14
0
    def timing(cls, func, times):
        """
        定时任务.
        在交易日执行定时任务
        :param times:
        :param func:形如[[10, 0], [10, 30], [11, 0], [11, 30], [13, 30], [14, 0], [14, 30], [15, 0]]
        这会使得func在每个交易日的10点、10点30分···执行
        :return:
        """
        try:
            warnings.warn(
                "The function  will be deprecated\n"
                "Please use \033[91m DScheduler\033[0m instead.",
                DeprecationWarning,
                stacklevel=2,
            )

            def merge(h, m):
                return pd.Timedelta(hours=h, minutes=m)

            times['time'] = times.apply(
                lambda r: merge(r['hour'], r['minute']), axis=1)
            times['log'] = pd.datetime(2018, 1, 1)

            def tim(tms):
                while 1:
                    try:
                        crt = dt.datetime.now()
                        if not trading.is_trade_day(crt):
                            print('{0} today is not in business'.format(crt))
                            time.sleep(60 * 60 * 2)  # sleep two hours
                            continue
                        tms['date'] = pd.datetime(crt.year, crt.month,
                                                  crt.day) + tms.time
                        tm = tms[tms.hour == crt.hour]
                        if len(tm):
                            for i, r in tm.iterrows():
                                if crt >= r.date != r.log:
                                    print('timing task run', r.date, r.log)
                                    func()
                                    tms.at[i, 'log'] = r.date
                                    pass
                            time.sleep(60)
                        else:
                            time.sleep(60 * 60)
                        pass
                    except Exception as ep:
                        ExceptionInfo(ep)

            t = threading.Thread(target=tim, args=(times, ))
            t.start()
        except Exception as e:
            ExceptionInfo(e)
Example #15
0
 def trade_days(cls, start, end):
     """
     给定两个时间,计算这个时间段内有多少个交易日
     :param start:
     :param end:
     :return:
     """
     try:
         cal = Calendar(workdays=cls.workdays, holidays=cls.holidays)
         days = cal.busdaycount(start, end)
         return days
     except Exception as e:
         ExceptionInfo(e)
         return 0
Example #16
0
 def is_trade_day(cls, date, holidays=None):
     """
     判断给定的这个时间是否是交易日(以日记)
     :param date: 需要判断的时间
     :return:
     """
     try:
         holidays = cls.holidays if holidays is None else holidays
         cal = Calendar(workdays=cls.workdays, holidays=holidays)
         flag = cal.isbusday(dt.datetime(date.year, date.month, date.day))
         return flag
     except Exception as e:
         ExceptionInfo(e)
         return False
Example #17
0
 def rrads(cls, date, n):
     """
     财务报表公布前或后n个交易日提请入市注意
     :param date:
     :return:
     """
     try:
         aim = trading.trade_period(date, n)
         lt = {'$gte': aim, '$lte': date} if n < 0 else {'$gte': date, '$lte': aim}
         rds = BaseData.read_RRADS(last_time=lt)
         return rds.loc[:, ['stock_code', 'stock_name', 'last_time']]
     except Exception as e:
         ExceptionInfo(e)
         return pd.DataFrame()
Example #18
0
                        def action_end(args):
                            print(fontcolor.F_GREEN + '-' * 80)
                            print('Calf-Note:end task running on ',
                                  dt.datetime.now(tz=tz))
                            print('-' * 80 + fontcolor.END)
                            try:

                                def end(**args):
                                    action.end(**args)

                                t = threading.Thread(target=end, args=(args, ))
                                t.start()
                            except Exception as ep:
                                ExceptionInfo(ep)
Example #19
0
 def trade_period(cls, start, days, holidays=None):
     """
     计算某个时间x个交易日后的时间,或之前(days为一个负数)
     :param start:
     :param days:
     :return:
     """
     try:
         holidays = cls.holidays if holidays is None else holidays
         cal = Calendar(workdays=cls.workdays, holidays=holidays)
         end = cal.addbusdays(start, days)
         return end
     except Exception as e:
         ExceptionInfo(e)
         return start
Example #20
0
 def update_data(self, table_name, condition, **kw):
     """
     按condition条件更新table_name表数据
     :param table_name:
     :param condition: 形如{‘date':datetime.datetime(2018,1,1)}的一个字典
     :param kw:形如close=0这样的参数组
     :return:
     """
     try:
         r = BaseModel(table_name, self.location,
                       self.dbname).update_batch(condition, kw)
         return r
     except Exception as e:
         ExceptionInfo(e)
         raise MongoIOError('Failed with update by MongoDB')
Example #21
0
                        def action_execute(args):
                            print(fontcolor.F_GREEN + '-' * 80)
                            print('Calf-Note:execute task running on ',
                                  dt.datetime.now(tz=tz))
                            print('-' * 80 + fontcolor.END)
                            try:

                                def exe(**args):
                                    action.execute(**args)

                                t = threading.Thread(target=exe, args=(args, ))
                                t.start()
                                t.join(execute_interval - 1)
                                # action.execute(args=args)
                            except Exception as ep:
                                ExceptionInfo(ep)
Example #22
0
 def read_one(self, table_name, field=None, **kw):
     """
     有时候只需要读一条数据,没必要使用read_data,
     :param table_name:
     :param field:
     :param kw:
     :return: a dict or None
     """
     try:
         cursor = BaseModel(table_name, self.location,
                            self.dbname).query_one(kw, field)
     except Exception as e:
         ExceptionInfo(e)
         cursor = None
     finally:
         return cursor
Example #23
0
 def modelparammodify(cls, **kw):
     """
     修改基本参数的值
     :param kw:
     :return:
     """
     try:
         keys = cls.model_param.keys()
         for k, v in zip(kw.keys(), kw.values()):
             if k in keys:
                 cls.model_param[k] = v
             else:
                 message = 'no find this key=%s in models param' % k
                 raise warning(message)
     except Exception as e:
         ExceptionInfo(e)
Example #24
0
 def real_profit(cls, data):
     """
     计算实时收益
     :param data:信号片集,来自于signals表
     :return:
     """
     try:
         real_data = rd.get_stocks_data(list(data.stock_code))
         data = pd.merge(data, real_data, on='stock_code')
         data['price'] = data.price.astype('float')  # 实时价格
         data['profit'] = (data.price - data.open_price) / data.open_price
         data.fillna(0, inplace=True)
         return data
     except Exception as e:
         ExceptionInfo(e)
         return pd.DataFrame()
Example #25
0
 def hk_stock_data(cls, stock_code):
     try:
         if isinstance(stock_code, str):
             _code = 'hk' + stock_code
             stock_code = [stock_code]
         elif isinstance(stock_code, list):
             _code = ['hk' + c for c in stock_code]
             _code = ','.join(_code)
         else:
             raise TypeError('This stock code type must in (str, list)')
         html = urlopen('http://hq.sinajs.cn/list={}'.format(_code)).read()
         data_l = html.decode('gbk').split('\n')
         i = 0
         res = dict()
         for data in data_l:
             if len(data):
                 d = data.split('="')
                 key = stock_code[i]
                 res[i] = [stock_code[i]] + d[1][:-2].split(',')
                 i += 1
         data = pd.DataFrame(res).T
         data[18] = data[18] + ' ' + data[19]
         data = data.loc[:, [0, 2, 3, 4, 5, 6, 7, 9, 10, 11, 12, 13, 18]]
         columns = {
             0: 'stock_code',
             2: 'stock_name',
             3: 'open',
             4: 'last_close',
             5: 'price',
             6: 'low',
             7: 'high',
             9: 'gains',
             10: 'B1',
             11: 'S1',
             12: 'amount',
             13: 'volume',
             18: 'datetime'
         }
         data = data.rename(columns=columns)
         data['datetime'] = pd.to_datetime(data.datetime)
         # data['stock_code'] = data.index
         # print(data.T)
         return data
     except Exception as e:
         ExceptionInfo(e)
         return None
Example #26
0
 def finally_datetime(cls,
                      date,
                      max_pst_days=1,
                      max_pst_hour=14,
                      max_pst_min=55,
                      bsi=False,
                      market=None):
     """
     根据开仓时间和最长持有时间计算买出时间,默认适用于中国A股股票
     :param max_pst_min:
     :param max_pst_hour:
     :param bsi: False表示按自然日计算持有的时间, True表示按交易日计算
     :param date:
     :param max_pst_days:
     :param market: 作用的市场
     :return:
     """
     try:
         tra = trading(market)
         time = dt.timedelta(hours=max_pst_hour, minutes=max_pst_min)
         start = dt.datetime(date.year, date.month, date.day)
         if bsi:
             end = tra.trade_period(start, max_pst_days)
             return end + time
         else:
             end = start + dt.timedelta(days=max_pst_days)
             if tra.is_trade_day(end):
                 return end + time
             else:  # end 不是交易日
                 if tra.trade_days(start, end) > 0:  # 向前推算
                     # for i in range(1, max_pst_days, 1):
                     #     end = end - dt.timedelta(days=1)
                     #     if tra.is_trade_day(end):
                     #         return end + time
                     end = tra.trade_period(end, -1)
                 else:  # 向后推算
                     # for i in range(1, 11, 1):
                     #     end = start + dt.timedelta(days=i)
                     #     if tra.is_trade_day(end):
                     #         return end + time
                     end = tra.trade_period(end, 1)
                 return end + time
             return date
     except Exception as e:
         ExceptionInfo(e)
         return date
Example #27
0
 def set_kline_update_log(cls, self, **kw):
     try:
         keys = self.keys()
         for k, v in zip(kw.keys(), kw.values()):
             if k in keys:
                 self[k] = v
             else:
                 print(WarningMessage('not find this key in original file'))
         self['datetime'] = dt.datetime.strftime(dt.datetime.today(),
                                                 '%Y-%m-%d %H:%M:%S')
         with open(project_dir + '/Calf/kline_update_log.json',
                   'w') as file:
             file.write(json.dumps(self))
         return self
     except Exception as e:
         ExceptionInfo(e)
         return self
Example #28
0
 def read_account_info(cls, **kw):
     """
     读取账户-订阅
     :return:
     """
     try:
         cursor = MODEL_TABLE(cls.location, cls.dbname,
                              'accounts').query(kw)
         if cursor.count():
             data = pd.DataFrame(list(cursor))
             return data
         else:
             return pd.DataFrame()
     except Exception as e:
         ExceptionInfo(e)
         return pd.DataFrame()
     pass
Example #29
0
 def read_one(cls, code, date, kline, **kw):
     """
     读取某只代码的某个时间点的K线数据,这个功能在read_data中也可以完成,
     但是这里单独实现是为了更好的性能。
     :param code:
     :param date:
     :param kline:
     :return:返回的是一个字典{}
     """
     try:
         sql = dict(stock_code=code, date=date)
         sql = dict(sql, **kw)
         cursor = KLINE_MODEL_TABLE(cls.location, cls.dbname,
                                    kline).query_one(sql)
         return cursor
     except Exception as e:
         ExceptionInfo(e)
         return None
Example #30
0
 def aggregate(self, table_name, pipeline):
     """
     :param table_name:
     :param pipeline: a list, 每一个元素相当于一个管道操作,常见的操作包括
     匹配('$match')、属性域选择('$project')
     :return: 
     """
     try:
         cursor = BaseModel(table_name, self.location,
                            self.dbname).aggregate(pipeline)
         # data = pd.DataFrame()
         # if cursor.count():
         data = pd.DataFrame(list(cursor))
         cursor.close()
         return data
     except Exception as e:
         ExceptionInfo(e)
         return pd.DataFrame()