def _xform_data(self, df): columns = [] tables_ = data.get_tables(self.hypers.arbitrage) percent = self.hypers.pct_change for table in tables_: name, cols, ohlcv = table['name'], table['cols'], table.get( 'ohlcv', {}) columns += [self._diff(df[f'{name}_{k}'], percent) for k in cols] # Add extra indicator columns if ohlcv and self.hypers.indicators: ind = pd.DataFrame() # TA-Lib requires specifically-named columns (OHLCV) for k, v in ohlcv.items(): ind[k] = df[f"{name}_{v}"] columns += [ ## Original indicators from some boilerplate repo I started with self._diff(SMA(ind, timeperiod=15), percent), self._diff(SMA(ind, timeperiod=60), percent), self._diff(RSI(ind, timeperiod=14), percent), self._diff(ATR(ind, timeperiod=14), percent), ## Indicators from the book "How to Day Trade For a Living". Not sure which are more solid... ## Price, Volume, 9-EMA, 20-EMA, 50-SMA, 200-SMA, VWAP, prior-day-close # self._diff(EMA(ind, timeperiod=9)), # self._diff(EMA(ind, timeperiod=20)), # self._diff(SMA(ind, timeperiod=50)), # self._diff(SMA(ind, timeperiod=200)), ] states = np.nan_to_num(np.column_stack(columns)) prices = df[data.target].values # Note: don't scale/normalize here, since we'll normalize w/ self.price/step_acc.cash after each action return states, prices
def ChartKBar_MA(KBar,longPeriod=20,shortPeriod=5): # 計算移動平均線(長短線) KBar['MA_long']=SMA(KBar,timeperiod=longPeriod) KBar['MA_short']=SMA(KBar,timeperiod=shortPeriod) # 將K線轉為DataFrame Kbar_df=KbarToDf(KBar) # 將副圖繪製出來 addp=[] addp.append(mpf.make_addplot(Kbar_df['MA_long'],color='red')) addp.append(mpf.make_addplot(Kbar_df['MA_short'],color='yellow')) # 開始繪圖 ChartKBar(KBar,addp,True)
def algo_action(self): #数据转换,方便调用ta-lib函数进行技术指标的计算,这里用SMA指标 close = np.asarray(self.close_buffer) ma = SMA({'close':close}, timeperiod=self.timeperiod) delta = round(close[-1] - ma[-1],4) # 最新数据点,bar的收盘价跟ma的差 last_ma = round(ma[-1], 4) # 均线ma的最新值 momentum = round(self.last_price - last_ma,4) # 当前最新价格跟ma之间的差,成交价相对ma偏离 cross = (close[-1] - ma[-1]) * (close[-3] - ma[-3]) < 0 ## 判断有否交叉 #print 'close: ', close print(('close ma delta: {0}, last_ma: {1}, momentum: {2}'.format(delta, last_ma, momentum))) b_p = self.get_position(self.exchange, self.sec_id, OrderSide_Bid) #查询策略所持有的多仓 # 打印持仓信息 print(('pos long: {0} vwap: {1:.2f}'.format(b_p.volume if b_p else 0.0, b_p.vwap if b_p else 0.0))) if cross < 0 and delta > threshold and momentum >= significant_diff: ## 收盘价上穿均线,且当前价格偏离满足门限过滤条件,多信号 # 没有超出下单次数限制 if self.trade_count < self.trade_limit: # 依次获取下单的交易量,下单量是配置的一个整数数列,用于仓位管理,可用配置文件中设置 vol = self.trade_unit[self.trade_count] # 如果本次下单量大于0, 发出买入委托交易指令 if vol > eps: self.open_long(self.exchange, self.sec_id, self.last_price, vol) self.trade_count += 1 #增加计数 elif cross < 0 and delta < -threshold and momentum <= - significant_diff: ## bar 收盘价下穿ma均线,且偏离满足信号过滤条件 # 超出下单次数限制 if b_p and b_p.available_yesterday > eps: self.close_long(self.exchange, self.sec_id, self.last_price, b_p.available_yesterday) self.trade_count = 0 else: ## 其他情况,忽略不处理 pass
def sma(self, data, length, price_input='close'): sma_values = {'success': True, 'result': {'data': None, 'current': None}}#, 'state': None}} data_copy = data.copy() try: # uses open prices? results = SMA(data_copy, timeperiod=length, price='close') sma_values['result']['data'] = results sma_values['result']['current'] = results[-1] if self.serialize_numpy == True: sma_values['result']['data'] = sma_values['result']['data'].tolist() except Exception as e: logger.exception('Exception while calculating SMA.') logger.exception(e) sma_values['success'] = False finally: return sma_values
def __init__(self, candles: dict, indicator_info: dict): self.candles = candles self.LENGTH = indicator_info[LENGTH] self.MA = SMA(candles, timeperiod=self.LENGTH)
def algo_action(self): #数据转换,方便调用ta-lib函数进行技术指标的计算,这里用SMA指标 close = np.asarray(self.close_buffer) ma = SMA({'close': close}, timeperiod=self.timeperiod) delta = round(close[-1] - ma[-1], 4) # 最新数据点,bar的收盘价跟ma的差 last_ma = round(ma[-1], 4) # 均线ma的最新值 momentum = round(self.last_price - last_ma, 4) # 当前最新价格跟ma之间的差,成交价相对ma偏离 #print 'close: ', close print('close ma delta: {0}, last_ma: {1}, momentum: {2}'.format( delta, last_ma, momentum)) a_p = self.get_position(self.exchange, self.sec_id, OrderSide_Ask) #查询策略所持有的空仓 b_p = self.get_position(self.exchange, self.sec_id, OrderSide_Bid) #查询策略所持有的多仓 # 打印持仓信息 print('pos long: {0} vwap: {1}, pos short: {2}, vwap: {3}'.format( b_p.volume if b_p else 0.0, round(b_p.vwap, 2) if b_p else 0.0, a_p.volume if a_p else 0.0, round(a_p.vwap, 2) if a_p else 0.0)) if delta > threshold and momentum >= significant_diff: ## 收盘价上穿均线,且当前价格偏离满足门限过滤条件,多信号 # 没有空仓,且没有超出下单次数限制 if (a_p is None or a_p.volume < eps) and self.trade_count < self.trade_limit: # 依次获取下单的交易量,下单量是配置的一个整数数列,用于仓位管理,可用配置文件中设置 vol = self.trade_unit[self.trade_count] # 如果本次下单量大于0, 发出买入委托交易指令 if vol > eps: self.open_long(self.exchange, self.sec_id, self.last_price, vol) self.trade_count += 1 #增加计数 else: # 如果有空仓,且达到本次信号的交易次数上限 if a_p and a_p.volume > eps and self.trade_count == self.trade_limit: self.close_short(self.exchange, self.sec_id, self.last_price, a_p.volume) # 平掉所有空仓 self.trade_count = 0 else: # 有空仓时,且上次交易信号后没达到交易次数限制,继续加空 vol = self.trade_unit[ self. trade_count] if self.trade_count < self.trade_limit else 0.0 self.trade_count += 1 if vol > eps: self.open_short(self.exchange, self.sec_id, self.last_price, vol) elif delta < -threshold and momentum <= -significant_diff: ## bar 收盘价下穿ma均线,且偏离满足信号过滤条件 # 没有多仓时,开空 if (b_p is None or b_p.volume < eps) and self.trade_count < self.trade_limit: vol = self.trade_unit[self.trade_count] self.trade_count += 1 if vol > eps: self.open_short(self.exchange, self.sec_id, self.last_price, vol) else: # 已有多仓,且达到了交易次数限制,平掉多仓 if b_p and b_p.volume > eps and self.trade_count == self.trade_limit: self.close_long(self.exchange, self.sec_id, self.last_price, b_p.volume) self.trade_count = 0 else: # 已有多仓,且没有达到交易次数限制,继续加多 vol = self.trade_unit[ self. trade_count] if self.trade_count < self.trade_limit else 0.0 self.trade_count += 1 if vol > eps: self.open_long(self.exchange, self.sec_id, self.last_price, vol) else: ## 其他情况,忽略不处理 ## get positions and close if any #self.trade_count = 0 ## reset trade count pass
def algo_action(self): close = np.asarray(self.close_buffer) if len(close) < self.life_timeperiod: self.logger.info('data not enough! len = {0}'.format(len(close))) return sma = SMA({'close': close}, timeperiod=self.short_timeperiod) lma = SMA( {'close': close}, timeperiod=self.long_timeperiod) ## make sure last lma is a number life = SMA({'close': close}, timeperiod=self.life_timeperiod) s_l_ma_delta = sma[-1] - lma[-1] ## 最新的短长MA差值 last_ma = sma[-1] ## 最新的短MA #momentum = self.momentum = sma[-1] - sma[-2] ## MA冲量 momentum = self.momentum = self.last_price - sma[-1] ## 当前价格相对MA冲量 ## 短MA变动趋势,true表示进入趋势,false表示震荡 moving_long = self.moving_long = moving_short = self.moving_short = False sma_diff = sma[-1] - sma[-2] sma_diff_1 = sma[-2] - sma[-3] moving = self.moving = sma_diff * sma_diff_1 > 0 if moving and (sma_diff * momentum > 0 or momentum >= self.momentum_factor * s_l_ma_delta): moving_long = self.moving_long = True elif moving and (sma_diff * momentum > 0 or momentum <= self.momentum_factor * s_l_ma_delta): moving_short = self.moving_short = True ## 均线是多头还是空头排列 long_trends = self.long_trends = (sma[-1] > lma[-1] > life[-1]) short_trends = self.short_trends = (sma[-1] < lma[-1] < life[-1]) self.logger.info('short ma: {0}, long ma: {1}, life line: {2}'.format( round(sma[-1], 4), round(lma[-1], 4), round(life[-1], 4))) self.logger.info( 'short long ma delta: {0}, last_ma: {1}, momentum: {2}'.format( round(s_l_ma_delta, 4), round(last_ma, 4), round(momentum, 4))) self.logger.info( '## short ma moving long: {0}, moving short: {1}; Trends is long: {2}, is short: {3}.' .format(moving_long, moving_short, long_trends, short_trends)) if self.analyse_only: return ## 下单基准价,为了能够成交,所有开平仓都会根据配置的跳数追价,这里先计算基准价格 price_base = max(self.last_price, close[-1]) if long_trends else (min( self.last_price, close[-1]) if short_trends else self.last_price) self.logger.info("current trade count = {0}, price base = {1} ".format( self.trade_count, round(price_base, 1))) self.care_positions() b_p = self.b_p # cancel unfinished orders #self.cancel_unfinished_orders() threshold = self.threshold significant_diff = self.significant_diff stop_lose_threshold = self.stop_lose_threshold stop_profit_threshold = self.stop_profit_threshold ## 多信号 if long_trends: ## short ma cross up long ma ## 没有多仓 if (b_p is None or b_p.volume < eps): signal_filter = ( moving_long or momentum >= significant_diff ) and s_l_ma_delta > threshold and self.trade_count < self.trade_limit vol = self.trade_unit[ self.trade_count] ## get order volume from configured list if signal_filter and vol > eps: self.trade_count += 1 ord_price = price_base + self.hops * self.tick_size self.logger.info( "open long ... count {0}, {1} @ {2}".format( self.trade_count, vol, ord_price)) self.open_long(self.exchange, self.sec_id, ord_price, vol) ## 有多仓,且有止赢要求 elif b_p and b_p.volume > eps: checking_limit = self.trade_count == self.trade_limit ## 最大交易次数限制止赢 b_pnl = self.last_price - b_p.vwap ## 多仓浮赢 if self.positive_stop and (checking_limit or b_pnl >= stop_profit_threshold): ord_price = price_base - self.hops * self.tick_size self.logger.info( "trade count {0} to limit time[{1}], stop profit, close long @ {2}" .format(self.trade_count, self.trade_limit, ord_price)) self.close_long_positions(b_p, ord_price) self.trade_count = 0 elif moving_short: ## 短线趋势反转,检查是否要riskoff self.try_stop_action() else: pass ## 空信号 elif short_trends: ## short ma cross down long ma ## 有多仓 if b_p and b_p.volume > eps: self.logger.info("trend changed, stop lose, close long") self.close_long_positions(b_p) self.trade_count = 0 else: pass else: ## check if need to stop trading, close all positions self.logger.info("no trends, here check if need to stop ...") self.try_stop_action()
from talib.abstract import SMA,EMA import sys # 登入帳號密碼(讀者須修正該帳號密碼為自己的,否則無法執行策略) GOrder.Login('TestAccount','TestPasswd') # 建立部位管理物件 OrderRecord=Record() # 取得回測參數、移動停損點數 StartDate=sys.argv[1] EndDate=sys.argv[2] LongMAPeriod=int(sys.argv[3]) ShortMAPeriod=int(sys.argv[4]) MoveStopLoss=float(sys.argv[5]) # 回測取報價物件 KBar=GOrder.GetTAKBar(StartDate,EndDate,'3008','Stock','0','5') KBar['MA_long']=SMA(KBar,timeperiod=LongMAPeriod) KBar['MA_short']=EMA(KBar,timeperiod=ShortMAPeriod) # 開始回測 for n in range(0,len(KBar['time'])-1): # 先判斷long MA的上一筆值是否為空值 再接續判斷策略內容 if not np.isnan( KBar['MA_long'][n-1] ) : # 如果無未平倉部位 if OrderRecord.GetOpenInterest()==0 : # short MA 向上突破 long MA if KBar['MA_short'][n-1] <= KBar['MA_long'][n-1] and KBar['MA_short'][n] > KBar['MA_long'][n] : OrderRecord.Order('Buy', KBar['product'][n+1],KBar['time'][n+1],KBar['open'][n+1],1) OrderPrice = KBar['open'][n+1] StopLossPoint = OrderPrice * (1 - MoveStopLoss) continue # short MA 向下突破 long MA if KBar['MA_short'][n-1] >= KBar['MA_long'][n-1] and KBar['MA_short'][n] < KBar['MA_long'][n] :
def getSMA(self, period=50): try: return SMA(self.data, timeperiod=period) except: raise TALIB_CALC_ERROR("SMA Calculation Error")