def return_cycle(cycle_context, cycle): kline = api.get_kline_serial(type, cycle) close = kline['close'] M20 = tafunc.ma(close, 20) M40 = tafunc.ma(close, 40) DIFF = tafunc.ema(close, 12) - tafunc.ema(close, 26) DEA = tafunc.ema(DIFF, 9) DDEA2 = DEA > 2 #结算价上涨 KDEA2 = DEA < 2 #结算价下跌 settle = close DSETTLE = settle >= tafunc.ref(settle, 1) KSETTLE = settle <= tafunc.ref(settle, 1) dictionary = { 'M20': M20, 'M40': M40, 'DIFF': DIFF, 'DEA': DEA, 'DDEA2': DDEA2, 'KDEA2': KDEA2, 'DSETTLE': DSETTLE, 'KSETTLE': KSETTLE } return dictionary[cycle_context]
def find_boll_daily(self, start_id, dklines): p = 1 n = 5 new_df = pd.DataFrame() mid = tafunc.ma(dklines["close"], n) std = dklines["close"].rolling(n).std() new_df["mid"] = mid new_df["top"] = mid + p * std new_df["bottom"] = mid - p * std boll = new_df ma_ck = 0 j = 1 for i in range(j + 1, j + 3 + 1): ma_ck += list(boll["mid"])[-i] - list(boll["mid"])[-(i + 1)] #print(ma_ck) if (ma_ck > 0): self.boll_top = int( list(boll["mid"])[-(j + 1)] + std.iloc[-(j + 1)] * 1.3) self.boll_bottom = int( list(boll["mid"])[-(j + 1)] - std.iloc[-(j + 1)]) elif (ma_ck < 0): self.boll_top = int( list(boll["mid"])[-(j + 1)] + std.iloc[-(j + 1)]) self.boll_bottom = int( list(boll["mid"])[-(j + 1)] - std.iloc[-(j + 1)] * 1.3)
def find_boll_daily(self, start_id, dklines): ''' boll=BOLL(dklines, 6, 1.5) self.boll_bottom = list(boll["bottom"])[-2] self.boll_top = list(boll["top"])[-2] ''' p = 1 n = 5 new_df = pd.DataFrame() mid = tafunc.ma(dklines["close"], n) std = dklines["close"].rolling(n).std() new_df["mid"] = mid new_df["top"] = mid + p * std new_df["bottom"] = mid - p * std #boll=BOLL(dklines,5, 1) boll = new_df ma_ck = 0 j = 1 for i in range(j+1, j+3+1): ma_ck += list(boll["mid"])[-i] - list(boll["mid"])[-(i+1)] #print(ma_ck) if (ma_ck > 0): self.boll_top = int(list(boll["mid"])[-(j+1)] + std.iloc[-(j+1)]*1.2) self.boll_bottom = int(list(boll["mid"])[-(j+1)] - std.iloc[-(j+1)]) self.boll_trade_dir = TradeDirection.BUYONLY if (ma_ck < 0): self.boll_top = int(list(boll["mid"])[-(j+1)] + std.iloc[-(j+1)]) self.boll_bottom = int(list(boll["mid"])[-(j+1)] - std.iloc[-(j+1)]*1.2) self.boll_trade_dir = TradeDirection.SELLONLY '''
def get_ma_key(self, klines): ma_list = [5, 10, 20, 30, 40, 60] list_len = len(ma_list) for i in range(0, list_len): ma = tafunc.ma(klines.close, ma_list[i]) name = "ma%d" % (ma_list[i]) relative_position = "cross" #above、below、cross last_crossup = 60 last_crossdown = 60 if (klines.iloc[-1].low > ma.iloc[-1]): relative_position = "above" elif (klines.iloc[-1].high < ma.iloc[-1]): relative_position = "below" # last_crossup for j in range(1, 100): if (klines.iloc[-j].low >= ma.iloc[-j] and klines.iloc[-(j + 1)].low <= ma.iloc[-(j + 1)]): last_crossup = j break #last_crossdown for j in range(1, 100): if (klines.iloc[-j].high <= ma.iloc[-j] and klines.iloc[-(j + 1)].high >= ma.iloc[-(j + 1)]): last_crossdown = j break ''' if (relative_position == "above"): self.key_ll.loc[len(self.key_ll)] = [name, ma.iloc[-1], relative_position, last_crossup, last_crossdown] elif (relative_position == "below"): self.key_hh.loc[len(self.key_hh)] = [name, ma.iloc[-1], relative_position, last_crossup, last_crossdown] ''' self.keys.loc[len(self.keys)] = [ name, ma.iloc[-1], relative_position, last_crossup, last_crossdown ]
def generate_event(self, klines): #key_len = len(self.key_ll) #for ll in self.key_ll: #c = ['tag', 'title', 'first', 'second'] c = [ 'tag', 'first_crossover', 'send_crossover', 'first_crossdown', 'send_crossdown', 'first_stick', 'send_stick' ] self.cross = pd.DataFrame(columns=c) kpattern_list = [] #KPattern ma_list = [5, 10, 20, 30, 40, 60] list_len = len(ma_list) for i in range(0, list_len): ma = tafunc.ma(klines.close, ma_list[i]) name = "ma%d" % (ma_list[i]) first_cd, send_cd = self.two_crossdown(list(ma), klines) #self.cross.loc[len(self.cross)] = [name, "two_crossdown", first_bar, send_bar] print("two_crossdown", name, first_cd, send_cd) first_cu, send_cu = self.two_crossover(list(ma), klines) self.cross.loc[len(self.cross)] = [ name, first_cd, send_cd, first_cu, send_cu, 100, 100 ] print("two_crossdown", name, first_cu, send_cu) key_name = ["bottom", "top", "mid"] boll = BOLL(klines, self.BOLL_TERM, self.BOLL_DIF) for i in range(0, 3): name = key_name[i] first_cd, send_cd = self.two_crossdown(list(boll[key_name[i]]), klines) #self.cross.loc[len(self.cross)] = [name, "two_crossdown", first_bar, send_bar] print("two_crossdown", name, first_cd, send_cd) first_cu, send_cu = self.two_crossover(list(boll[key_name[i]]), klines) self.cross.loc[len(self.cross)] = [ name, first_cd, send_cd, first_cu, send_cu, 100, 100 ] print("two_crossover", name, first_cu, send_cu) for index, row in self.cross.iterrows(): first_cu = row['first_crossover'] send_cu = row['send_crossover'] first_cd = row['first_crossdown'] send_cd = row['send_crossdown'] #print(row['first_bar'], row['send_bar']) if (first_cu < 4 and first_cd > 5 and send_cu - first_cu > 15): #key_price 支撑 print("StdCrossGoBack up") print(row) #==== kpt = KPBackFromKeySupportLine(1) kpt.bar = first_cu kpattern_list.append(kpt) if (first_cu > 5 and first_cd < 4 and send_cd - first_cd < 15): #key_price 反转 print("StdCrossReverse") print(row) #========= kpt = KPBackFromKeyResistanceLine(1) kpt.bar = first_cd kpattern_list.append(kpt) return kpattern_list
# "duration_seconds=60"为一分钟线, 日线的duration_seconds参数为: 24*60*60 klines = api.get_kline_serial(SYMBOL, duration_seconds=1*60, data_length=data_length) #收盘后不可查 target_pos = TargetPosTask(api, SYMBOL) position = api.get_position(SYMBOL)#指定一个品种查看持仓相关信息 account = api.get_account()#获取用户账户资金信息 while True: api.wait_update() if api.is_changing(klines.iloc[-1], "datetime"): # 产生新k线:重新计算SMA klines["ma5"]=ma(klines["close"], 5) klines["ma10"]=ma(klines["close"], 10) klines["ma89"]=ma(klines["close"], 89) klines["ma144"]=ma(klines["close"], 144) sar=SAR(klines, 4, 0.02, 0.2) if api.is_changing(klines.iloc[-1], "datetime"): # 产生新k线:重新计算SMA if klines['close'].iloc[-1] < klines['ma89'].iloc[-2]: if klines["ma5"].iloc[-2] < klines["ma10"].iloc[-2] and klines["ma10"].iloc[-1] > klines["ma5"].iloc[-1]: target_pos.set_target_volume(-1) print("均线下穿,做空") elif klines["close"].iloc[-2] > klines["ma5"].iloc[-2]: target_pos.set_target_volume(0) print("均线上穿,平空") # 均线上穿,做多
SYMBOL = "SHFE.bu1912" # 合约代码 api = TqApi() print("策略开始运行") data_length = LONG + 2 # k线数据长度 # "duration_seconds=60"为一分钟线, 日线的duration_seconds参数为: 24*60*60 klines = api.get_kline_serial(SYMBOL, duration_seconds=60, data_length=data_length) target_pos = TargetPosTask(api, SYMBOL) while True: api.wait_update() if api.is_changing(klines.iloc[-1], "datetime"): # 产生新k线:重新计算SMA short_avg = ma(klines["close"], SHORT) # 短周期 long_avg = ma(klines["close"], LONG) # 长周期 # 均线下穿,做空 if long_avg.iloc[-2] < short_avg.iloc[-2] and long_avg.iloc[ -1] > short_avg.iloc[-1]: target_pos.set_target_volume(-3) print("均线下穿,做空") # 均线上穿,做多 if short_avg.iloc[-2] < long_avg.iloc[-2] and short_avg.iloc[ -1] > long_avg.iloc[-1]: target_pos.set_target_volume(3) print("均线上穿,做多")
def double_moving_average(api: TqApi, symbol: str, max_position: int = 10, fast: int = 5, slow: int = 20): strategy_name: str = 'DoubleMovingAverage' api: TqApi = api symbol: str = symbol timeout: int = 5 max_position: int = max_position fast: int = fast slow: int = slow ma: DataFrame = DataFrame() tq_account: Account = api.get_account() tq_position: Position = api.get_position(symbol) tq_candlestick: DataFrame = api.get_kline_serial(symbol=symbol, duration_seconds=24 * 60 * 60) tq_target_pos = TargetPosTask(api, symbol) deadline: float try: while True: deadline = time.time() + timeout if not api.wait_update(deadline=deadline): raise RuntimeError('没有在规定时间内获得数据!') # api.wait_update() if api.is_changing(tq_candlestick): ma['fast'] = tafunc.ma(tq_candlestick.close, fast) ma['slow'] = tafunc.ma(tq_candlestick.close, slow) tq_candlestick['ma_fast'] = ma['fast'] tq_candlestick['ma_fast.color'] = 'green' tq_candlestick['ma_slow'] = ma['slow'] tq_candlestick['ma_slow.color'] = 0xFF9933CC # 最新的快均线数值 > 最新的慢均线数值,且 前一根快均线数值 < 前一根慢均线数值 # 即快均线从下向上穿过慢均线 if (ma['fast'].iloc[-1] > ma['slow'].iloc[-1] and ma['fast'].iloc[-2] < ma['slow'].iloc[-2]): # # 如果有空仓,平空仓 # if tq_position.pos_short > 0: # api.insert_order(symbol=symbol, # direction='BUY', # offset='CLOSE', # limit_price=tq_candlestick.close.iloc[-1], # volume=tq_position.pos_short # ) # # 开多仓 # api.insert_order(symbol=symbol, # direction='BUY', # offset='OPEN', # limit_price=tq_candlestick.close.iloc[-1], # volume=max_position # ) tq_target_pos.set_target_volume(max_position) # 最新的快均线数值 < 最新的慢均线数值,且 前一根快均线数值 > 前一根慢均线数值 # 即快均线从上向下穿过慢均线 if (ma['fast'].iloc[-1] < ma['slow'].iloc[-1] and ma['fast'].iloc[-2] > ma['slow'].iloc[-2]): # # 如果有多仓,平多仓 # if tq_position.pos_short > 0: # api.insert_order(symbol=symbol, # direction='SELL', # offset='CLOSE', # limit_price=tq_candlestick.close.iloc[-1], # volume=tq_position.pos_short # ) # # 开空仓 # api.insert_order(symbol=symbol, # direction='SELL', # offset='OPEN', # limit_price=tq_candlestick.close.iloc[-1], # volume=max_position # ) tq_target_pos.set_target_volume(-max_position) except BacktestFinished: api.close() print(f'参数: fast={fast}, slow={slow}, 最终权益={tq_account["balance"]}')
# 实盘交易 # api = TqApi(TqAccount("G光大期货","[账号]","[密码]"), web_gui=True) # 回测模式 from datetime import date api = TqApi(backtest=TqBacktest(date(2019, 7, 1), date(2019, 12, 1)), web_gui=True) # 策略初始化 symbol = "CFFEX.IF1912" klines = api.get_kline_serial(symbol, 60 * 15) # 订阅15分钟K线序列 target_pos = TargetPosTask(api, symbol) try: while True: api.wait_update() if api.is_changing(klines): # MA120的最新值 ma120 = ma(klines.close, 120).iloc[-1] # MA10上穿MA20的bool序列的最新值 up_cross = crossup(ma(klines.close, 10), ma(klines.close, 20)).iloc[-1] # MA10下穿MA20的bool序列的最新值 down_cross = crossdown(ma(klines.close, 10), ma(klines.close, 20)).iloc[-1] # 如果最新K线收盘价在MA120上方 if klines.close.iloc[-1] > ma120: # 如果MA10上穿MA20,开一手 if up_cross: target_pos.set_target_volume(1) # 如果MA10下穿MA20,平仓 elif down_cross: target_pos.set_target_volume(0) # 如果最新K线收盘价在MA120下方
def on_day_bar(self, dklines): self.ma10day = 0 ma = tafunc.ma(dklines.close, 20) self.ma20day = ma.iloc[-1] self.ma30day = 0 self.key_ma = 0 self.debug("key_price = %d" % (self.key_price)) if (self.key_price != 0): return #理论上用不到了,用KParser #get ma20 price if (dklines.iloc[-1].close > self.ma20day): last_crossup_ma = 30 for i in range(1, 30): if (dklines.iloc[-i].low > ma.iloc[-i] and dklines.iloc[-(i + 1)].low <= ma.iloc[-i]): last_crossup_ma = i break if (last_crossup_ma > 10): #支撑 #self.key_price = self.ma20day self.key_ma = self.ma20day elif (dklines.iloc[-1].close < self.ma20day): last_crossdown_ma = 30 for i in range(1, 30): if (dklines.iloc[-i].high < ma.iloc[-i] and dklines.iloc[-(i + 1)].high >= ma.iloc[-i]): last_crossdown_ma = i break if (last_crossdown_ma > 10): #阻力 #self.key_price = self.ma20day self.key_ma = self.ma20day # self.key_price = self.ma20day #获取反复触及的线 high_id = pplib.get_key_high_bar(dklines, 10) low_id = pplib.get_key_low_bar(dklines, 10) self.debug("hh_hard_touch high_id=%d" % (high_id)) self.debug("ll_hard_touch low_id=%d" % (low_id)) self.hh_hard_touch = 0 self.ll_hard_touch = 0 if (high_id < low_id and high_id < 5): self.hh_hard_touch = dklines.iloc[-high_id].high self.debug("hh_hard_touch=%d" % (self.hh_hard_touch)) elif (low_id < high_id and low_id < 5): self.ll_hard_touch = dklines.iloc[-low_id].low self.debug("ll_hard_touch=%d" % (self.ll_hard_touch)) self.KParser.on_bar(dklines) self.find_key_mode() kp_event = self.KParser.generate_event(dklines) self.boardcast_kpevent(kp_event) day_price = dklines.iloc[-1].close self.key_ll_ma = self.KParser.get_last_key_ll_price(day_price, 5) self.key_hh_ma = self.KParser.get_last_key_hh_price(day_price, 5) #平均price, 计算key priceCombine = PriceCombine() priceCombine.refer_price = day_price priceCombine.min_diff = -10 priceCombine.max_diff = 100 priceCombine.add(self.key_hh_ma) priceCombine.add(self.hh_hard_touch) key_hh = priceCombine.get() priceCombine.min_diff = -100 priceCombine.max_diff = 10 priceCombine.add(self.key_ll_ma) priceCombine.add(self.ll_hard_touch) key_ll = priceCombine.get() self.debug("final_key_hh=%d, final_key_ll=%d" % (key_hh, key_ll)) if (key_hh != 0): self.set_indor_value(Indicator.KeyHHPrice, key_hh) if (key_ll != 0): self.set_indor_value(Indicator.KeyLLPrice, key_ll)