class PeriodSimulate(Simulate): def __init__(self, stock_codes, judge_out_name, period=7): super().__init__(stock_codes, judge_out_name) self.period = period @staticmethod def get_sum_field(): return ['win_pct_less_than_50', 'win_pct_bigger_than_50', 'win_pct_bigger_than_60', 'win_pct_bigger_than_70'] def __call__(self, *args, **kwargs): self.data_center = DataCenter() if self.stock_codes is None or len(self.stock_codes) == 0: return # 统计所有的股票,在:param peirod期间之内的盈利情况 sum_dict = { 'win_pct_less_than_50': 0, 'win_pct_bigger_than_50': 0, 'win_pct_bigger_than_60': 0, 'win_pct_bigger_than_70': 0, } for stock_code in self.stock_codes: base_infos = self.data_center.fetch_base_data(stock_code) shift_close = base_infos['close'].shift(self.period) win_pct = (shift_close - base_infos['close']) / base_infos['close'] base_infos['win_pct'] = win_pct base_infos.drop(['vol', 'amount', 'pre_close', 'change'], axis=1, inplace=True) if not base_infos.empty: count_percent = len(base_infos[base_infos['win_pct'] > 0]) / len(base_infos) sum_dict['win_pct_less_than_50'] = sum_dict['win_pct_less_than_50'] + 1 if count_percent < 0.5 \ else sum_dict['win_pct_less_than_50'] sum_dict['win_pct_bigger_than_50'] = sum_dict['win_pct_bigger_than_50'] + 1 if count_percent >= 0.5 \ else sum_dict['win_pct_bigger_than_50'] sum_dict['win_pct_bigger_than_60'] = sum_dict['win_pct_bigger_than_60'] + 1 if count_percent >= 0.6 \ else sum_dict['win_pct_bigger_than_60'] sum_dict['win_pct_bigger_than_70'] = sum_dict['win_pct_bigger_than_70'] + 1 if count_percent >= 0.7 \ else sum_dict['win_pct_bigger_than_70'] sum_str = "win count percent is " + str(count_percent) file_name = "period_simulate_" + stock_code now_time = datetime.datetime.now() now_time_str = now_time.strftime('%Y%m%d') file_name += '_' + now_time_str file_name += '.csv' FileOutput.csv_output(None, base_infos, file_name, spe_dir_name=self.judge_out_name, extra_content=sum_str) return sum_dict
class Simulate: BUY_FLAG = 1 SOLD_FLAG = -1 DO_NOTHING = 0 MULTI_INDI_BETWEEN = 5 # 如果有多种指标,多少天之内均发出买入信号就决定买入 def __init__(self, stock_codes, judge_out_name, judge_time=None): self.initial_mny = None self.stock_codes = stock_codes self.judge_time = judge_time self.hold_num = 0 # 持仓手数 self.left_mny = 0 # 剩余金额 self.judge_out_name = judge_out_name # 判定输出目录名称 def set_registry(self, judge_time): self.judge_time = judge_time def set_judge_name(self, judge_name): self.judge_out_name = judge_name def set_init_mny(self, init_mny): """ 设置初始金额,金额为RMB :param init_mny: :return: """ self.initial_mny = init_mny self.left_mny = init_mny def reset(self): self.left_mny = self.initial_mny self.hold_num = 0 def __call__(self, *args, **kwargs): # TODO -- 看一下Python的数值计算方式,是否有小数??? self.data_center = DataCenter() final_sum_dict = { 'win_num': 0, 'lose_num': 0, 'max_win_pct': 0, 'max_lost_pct': 0, 'ave_win_mny': 0 } trade_rst = pandas.DataFrame(columns=('ts_code', 'trade_times', 'final_win', 'win_pct')) for stock_code in self.stock_codes: trade_rst_dict = { 'ts_code': stock_code, 'trade_times': 0, 'final_win': 0, 'win_pct': 0 } base_infos = self.data_center.fetch_base_data(stock_code) if base_infos is None or len(base_infos) == 0: continue ret_time = [] for item in self.judge_time: ret_time.append(item(base_infos)) if ret_time is None or len(ret_time) == 0: continue detail_trade_info = pandas.DataFrame( columns=('ts_code', 'curr_close', 'trade_date', 'trade_num', 'hold_num', 'hold_mny', 'total_mny')) if len(ret_time[0]) != len(base_infos): print("Not equals!!!") for i in range(len(ret_time[0])): # 判定是否是买入时机 operate_flag = self.DO_NOTHING temp_buy_pct = 0.1 for item in ret_time: # 从当前往前5天之内是否有发出过买入信号,如果有,就算有 start_index = i - self.MULTI_INDI_BETWEEN start_index = 0 if start_index < 0 else start_index temp_val = self.DO_NOTHING for j in range(start_index, i + 1): if item.at[j, 'flag'] == self.BUY_FLAG: temp_val = self.BUY_FLAG temp_buy_pct = item.at[j, 'percent'] if 0 < item.at[j, 'percent'] < temp_buy_pct \ else temp_buy_pct break elif item.at[j, 'flag'] == self.SOLD_FLAG: temp_val = self.SOLD_FLAG temp_buy_pct = item.at[j, 'percent'] if 0 < item.at[j, 'percent'] < temp_buy_pct \ else temp_buy_pct break if operate_flag == self.DO_NOTHING or operate_flag == temp_val: operate_flag = temp_val continue else: operate_flag = self.DO_NOTHING break if operate_flag == self.BUY_FLAG: # 默认买入10% buy_pct = temp_buy_pct buy_mny = self.initial_mny * buy_pct buy_mny = self.left_mny if self.left_mny < buy_mny else buy_mny buy_num = buy_mny / base_infos.at[i, 'close'] self.hold_num = self.hold_num + buy_num self.left_mny = self.left_mny - buy_mny hold_mny = self.hold_num * base_infos.at[i, 'close'] # 记录买入信息 temp_dict = { 'ts_code': stock_code, 'trade_date': base_infos.at[i, 'trade_date'], 'trade_num': buy_num, 'hold_num': self.hold_num, 'hold_mny': hold_mny, 'total_mny': self.left_mny + hold_mny, 'curr_close': base_infos.at[i, 'close'] } detail_trade_info = detail_trade_info.append(temp_dict, ignore_index=True) trade_rst_dict['trade_times'] = trade_rst_dict['trade_times'] + 1 elif operate_flag == self.SOLD_FLAG: # 默认卖出持仓数量的10% sold_pct = temp_buy_pct sold_num = self.hold_num * sold_pct sold_num = sold_num / 100 * 100 self.hold_num = self.hold_num - sold_num sold_mny = sold_num * base_infos.at[i, 'close'] self.left_mny = self.left_mny + sold_mny hold_mny = self.hold_num * base_infos.at[i, 'close'] # 记录卖出信息 temp_dict = { 'ts_code': stock_code, 'trade_date': base_infos.at[i, 'trade_date'], 'trade_num': sold_num, 'hold_num': self.hold_num, 'hold_mny': hold_mny, 'total_mny': self.left_mny + hold_mny, 'curr_close': base_infos.at[i, 'close'] } detail_trade_info = detail_trade_info.append(temp_dict, ignore_index=True) trade_rst_dict['trade_times'] = trade_rst_dict['trade_times'] + 1 if not detail_trade_info.empty: file_name = "simulate_" + str(stock_code) now_time = datetime.datetime.now() now_time_str = now_time.strftime('%Y%m%d') file_name += '_' + now_time_str file_name += '.csv' FileOutput.csv_output(None, detail_trade_info, file_name, spe_dir_name=self.judge_out_name) else: print("no such stock!") self.reset() if detail_trade_info.empty: continue # 统计该只股票的最终盈利 last_win = detail_trade_info.at[(len(detail_trade_info) - 1), 'total_mny'] - self.initial_mny last_win_pct = last_win / self.initial_mny trade_rst_dict['final_win'] = last_win trade_rst_dict['win_pct'] = last_win_pct trade_rst = trade_rst.append(trade_rst_dict, ignore_index=True) # 统计多只股票的汇总 final_sum_dict['win_num'] = final_sum_dict['win_num'] + 1 if last_win > 0 else final_sum_dict['win_num'] final_sum_dict['lose_num'] = final_sum_dict['lose_num'] + 1 if last_win <= 0 else final_sum_dict['lose_num'] final_sum_dict['max_win_pct'] = last_win_pct if last_win_pct > final_sum_dict['max_win_pct'] else \ final_sum_dict['max_win_pct'] final_sum_dict['max_lost_pct'] = last_win_pct if last_win_pct <= final_sum_dict['max_lost_pct'] else \ final_sum_dict['max_lost_pct'] sum_str = "获利数量:" + str(final_sum_dict['win_num']) + " 损失数量:" + str(final_sum_dict['lose_num']) \ + " 最大获利百分比:" + str(final_sum_dict['max_win_pct']) + " 最大损失百分比:" + \ str(final_sum_dict['max_lost_pct']) if not trade_rst.empty: file_name = "trade_group_" + self.stock_codes[0] now_time = datetime.datetime.now() now_time_str = now_time.strftime('%Y%m%d') file_name += '_' + now_time_str file_name += '.csv' FileOutput.csv_output(None, trade_rst, file_name, spe_dir_name=self.judge_out_name, extra_content=sum_str) return final_sum_dict
class MACDSelector: """ 通过MACD指标来选择对应的股票 """ BUY_SIGNAL_PERIOD = 2 # 两天之内发出买入信号的话,该只股票视为可买入 def __init__(self, ts_codes=None): if ts_codes is None: ts_codes = [] self.ts_codes = ts_codes self.fast = 12 self.slow = 26 self.signal = 9 def set_fast(self, fast): self.fast = fast def set_slow(self, slow): self.slow = slow def set_signal(self, signal): self.signal = signal def __call__(self, *args, **kwargs): self.data_center = DataCenter() if len(self.ts_codes) == 0: return result = pandas.DataFrame(columns=('ts_code', 'in_price', 'in_date', 'origin_from', 'in_reason', 'finished', 'manual')) for ts_code in self.ts_codes: field_suffix = "_" + str(self.fast) + "_" + str( self.slow) + "_" + str(self.signal) macd_field_name = 'MACD' + field_suffix histogram_field_name = 'MACDh' + field_suffix signal_field_name = 'MACDs' + field_suffix base_infos = self.data_center.fetch_base_data(ts_code) if base_infos is None or len(base_infos) == 0: continue close = base_infos['close'] macd_ret = ta.macd(close, self.fast, self.slow, signal=self.signal) if len(macd_ret) < 2: continue rst_length = len(macd_ret) start_index = min(rst_length, self.BUY_SIGNAL_PERIOD) start_index = rst_length - start_index low_flag = False for i in range(start_index, rst_length): if macd_ret.at[i, macd_field_name] is not None and macd_ret.at[i, signal_field_name] is not None and \ macd_ret.at[i, macd_field_name] < macd_ret.at[i, signal_field_name]: low_flag = True else: if low_flag: now_time = datetime.datetime.now() now_time_str = now_time.strftime('%Y%m%d') temp_dict = { 'ts_code': ts_code, 'in_price': close[i], 'in_date': base_infos.at[start_index, 'trade_date'], 'origin_from': 'macd', 'in_reason': 'macd金叉', 'finished': 0, 'manual': 0 } result = result.append(temp_dict, ignore_index=True) return result