def load_basic_info(self): try: print('Getting basic F10 info for CN..') stock_basic = ts.pro_api().stock_basic(list_status='L', fields='ts_code,symbol,name') # L是正在上市股票 self._basic_info['CN'] = stock_basic.set_index('symbol') # 以symbol('000001')为索引,有ts_code('000001.SZ'), name(中文名)两列 except BaseException as e: self._basic_info['CN'] = pd.DataFrame() print(f'Warning: Get stock F10 info from tushare failed: {e}') if self._futu_enabled: test_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: test_socket.connect((self._futu_host, self._futu_port)) test_socket.close() except socket.error as e: raise RuntimeError(f'{self._futu_host}:self._futu_port connect failed') from e quote_ctx = futu.OpenQuoteContext(host=self._futu_host, port=self._futu_port) print('Getting basic F10 info for HK..') return_code, data_df = quote_ctx.get_stock_basicinfo(futu.Market.HK, stock_type=futu.SecurityType.STOCK) if return_code == 0: self._basic_info['HK'] = data_df.set_index('code') else: self._basic_info['HK'] = pd.DataFrame() print(f'get data from futu error: {data_df}') print('Getting basic F10 info for US..') return_code, data_df = quote_ctx.get_stock_basicinfo(futu.Market.US, stock_type=futu.SecurityType.STOCK) if return_code == 0: self._basic_info['US'] = data_df.set_index('code') else: self._basic_info['US'] = pd.DataFrame() print(f'get data from futu error: {data_df}') quote_ctx.close()
def context_setting(self): """ API trading and quote context setting :returns: trade context, quote context """ if self.unlock_password == "": raise Exception("请先配置交易解锁密码! password: {}".format( self.unlock_password)) quote_ctx = ft.OpenQuoteContext(host=self.api_svr_ip, port=self.api_svr_port) if 'HK.' in self.stock: trade_ctx = ft.OpenHKTradeContext(host=self.api_svr_ip, port=self.api_svr_port) if self.trade_env == ft.TrdEnv.REAL: ret_code, ret_data = trade_ctx.unlock_trade( self.unlock_password) if ret_code == ft.RET_OK: print('解锁交易成功!') else: raise Exception("请求交易解锁失败: {}".format(ret_data)) else: print('解锁交易成功!') elif 'US.' in self.stock: if self.trade_env != 0: raise Exception("美股交易接口不支持仿真环境 trade_env: {}".format( self.trade_env)) trade_ctx = ft.OpenUSTradeContext(host=self.api_svr_ip, port=self.api_svr_port) else: raise Exception("stock输入错误 stock: {}".format(self.stock)) return quote_ctx, trade_ctx
def open_api(self): SQLog.info("open_api,quote already open=", self.is_open()) if self._quote_ctx is None: self._quote_ctx = futu.OpenQuoteContext(self.ApiIP, self.ApiPort) if self._trade_ctx is None: if self.Market == futu.Market.HK: self._trade_ctx = futu.OpenHKTradeContext( self.ApiIP, self.ApiPort) elif self.Market == futu.Market.US: self._trade_ctx = futu.OpenUSTradeContext( self.ApiIP, self.ApiPort) else: raise Exception("open_api failed,Market parameter wrong.") if self.EnvType == futu.TrdEnv.REAL: ret, data = self._trade_ctx.unlock_trade( self.TradePassword, self.TradePasswordMd5) if futu.RET_OK != ret: raise Exception( "open_api failed,unlock_trade failed,data=" + str(data)) ret, data = self._trade_ctx.get_acc_list() SQLog.debug("open_api,get_acc_list,ret=", ret, "data=\n", data) self._trade_ctx.set_handler(TradeOrderHanbler(self)) self._trade_ctx.set_handler(TradeDealHandler()) self._trade_ctx.start() super().open_api() if self.AveVolaStockCodes and self._frame: self._frame.load_savequote_data( self.AveVolaStockCodes.split(',')) return True
def context_setting(api_svr_ip, api_svr_port, unlock_password): quote_ctx = ft.OpenQuoteContext(host=api_svr_ip, port=api_svr_port) hk_trade_ctx = ft.OpenHKTradeContext(host=api_svr_ip, port=api_svr_port) ret_code, ret_data = hk_trade_ctx.unlock_trade(unlock_password) if ret_code != ft.RET_OK: hk_trade_ctx = None hkcc_trade_ctx = ft.OpenHKCCTradeContext(host=api_svr_ip, port=api_svr_port) ret_code, ret_data = hkcc_trade_ctx.unlock_trade(unlock_password) if ret_code != ft.RET_OK: hkcc_trade_ctx = None us_trade_ctx = ft.OpenUSTradeContext(host=api_svr_ip, port=api_svr_port) ret_code, ret_data = us_trade_ctx.unlock_trade(unlock_password) if ret_code != ft.RET_OK: us_trade_ctx = None return quote_ctx, hk_trade_ctx, hkcc_trade_ctx, us_trade_ctx
def futubase(): import futu as ft quote_ctx = ft.OpenQuoteContext(host='127.0.0.1', port=11111) quote_ctx.subscribe(['US.AMZN'], [ft.SubType.K_60M]) c = quote_ctx.get_cur_kline('US.AMZN', 1000, ft.SubType.K_60M, ft.AuType.QFQ) d = quote_ctx.get_history_kline('US.AMZN', start='2018-03-05', end='2018-07-29', ktype='K_DAY') quote_ctx.close()
def getDataFromFutu(code='US.AMZN', start='2010-01-01'): import futu as ft quote_ctx = ft.OpenQuoteContext(host='127.0.0.1', port=11111) ret, data = quote_ctx.get_history_kline(code, start, end='2099-01-01', ktype='K_DAY') return data
def saveToCsv(): import futu as ft quote_ctx = ft.OpenQuoteContext(host='127.0.0.1', port=11111) quote_ctx.subscribe(['US.AMZN'], [ft.SubType.K_30M]) ret, data = quote_ctx.get_history_kline('US.AMZN', start='2017-01-01', end='2019-01-01', ktype='K_30M') quote_ctx.close() if ret == ft.RET_OK: data.to_csv('amzn_30M_201701_201708.csv') print( 'csv printed' )
def get_DF_RSI(): import futu as ft import talib quote_ctx = ft.OpenQuoteContext(host='127.0.0.1', port=11111) # ret, data = quote_ctx.get_history_kline('US.AMZN', start='2017-01-01', end='2018-08-17', ktype='K_30M') ret, data = quote_ctx.get_cur_kline('US.AMZN', 1000, ft.SubType.K_60M, ft.AuType.QFQ) quote_ctx.close() if ret == ft.RET_OK: data['rsi13'] = talib.RSI(data['close'],13) return data
def __init__(self, password): """ https://futunnopen.github.io/futuquant/api/Market_API_Python_Doc.html """ self.quote_ctx = ft.OpenQuoteContext(host="127.0.0.1", port=11111) self.USTrade_ctx = ft.OpenUSTradeContext(host='127.0.0.1', port=11111) self.HKTrade_ctx = ft.OpenHKTradeContext(host='127.0.0.1', port=11111) self.quote_ctx.start() self.USTrade_ctx.start() self.HKTrade_ctx.start() self.password = password
def _opend_proc(q, ip=None, port=None): arg = {} if ip is not None: arg['host'] = ip if port is not None: arg['port'] = port quote_ctx = futu.OpenQuoteContext(**arg) ret, data = quote_ctx.get_global_state() if ret == futu.RET_OK: q.put(data['server_ver']) quote_ctx.close()
def _get_data_from_futu_opend(self, symbol: str, start: str) -> pd.DataFrame: quote_ctx = futu.OpenQuoteContext(host=self._futu_host, port=self._futu_port) today_date = time.strftime('%Y-%m-%d') # 以现在时间为准 NEWEST_TRADE_DATE只适用于中国市场 return_code, df, _ = quote_ctx.request_history_kline(symbol, start=start, end=today_date) if return_code != 0: # 最多重试一次 time.sleep(1) return_code, df, _ = quote_ctx.request_history_kline(symbol, start=start, end=today_date) if return_code != 0: quote_ctx.close() # 使线程退出 不阻塞主进程 raise RuntimeError(f'get data from futu error: {df}') # 返回的日期格式为'yyyy-mm-dd 00:00:00' 把后面的去掉 日期格式保持统一 df['time_key'] = df['time_key'].apply(lambda s: s.split(' ')[0]) df.set_index('time_key', inplace=True) # 改成按日期索引 quote_ctx.close() time.sleep(0.5) return df
def sell_all_at_market_price(self): (ret, result) = self.query_holdings() if ret == 0: logging.info("Query holdings OK: result=%s" % result) else: logging.warn("query holdings fail: ret=%d, result=%s" % (ret, result)) return -5, None #sell all holdings at market prices quote_context = ft.OpenQuoteContext(host='127.0.0.1', port=11111) for one_holding in result: if int(one_holding["amount"]) == 0: continue #subscript stock_code_w_prifix = stock_util.add_prifix( one_holding["stock_code"]) ret_status, ret_data = quote_context.subscribe( stock_code_w_prifix, "QUOTE") if ret_status != RET_OK: print("%s %s: %s" % (stock_code_w_prifix, "QUOTE", ret_data)) continue #query quote code_list = [] code_list.append(stock_code_w_prifix) ret_status, ret_data = quote_context.get_stock_quote(code_list) if ret_status == RET_ERROR: logging.info("get_stock_quote:stock_code=%s, msg=%s" % (code_list, ret_data)) continue now_price = ret_data["last_price"][0] sell_price = round(now_price * 0.99, 2) (ret, result) = self.buy_sell("S", one_holding["stock_code"], sell_price, one_holding["amount"]) if ret == 0: logging.info("Deal OK: order_id=%s" % result) else: logging.warn("Buy Or Sell Fail: ret=%d, ret_msg=%s" % (ret, result)) continue return 0, None
def simple_financial_filter(api_svr_ip, api_svr_port): """ 验证接口:条件选股功能 get_stock_filter 这里只设置了“简单属性”和“财务属性”作为筛选条件,。 :param api_svr_ip: (string)ip :param api_svr_port: (int)port :return: """ # 创建行情api quote_ctx = ft.OpenQuoteContext(host=api_svr_ip, port=api_svr_port) # 简单属性 simple_filter = ft.SimpleFilter() simple_filter.filter_min = 2 simple_filter.filter_max = 1000 simple_filter.stock_field = ft.StockField.CUR_PRICE simple_filter.is_no_filter = False # simple_filter.sort = SortDir.ASCEND # 财务属性 financial_filter = ft.FinancialFilter() financial_filter.filter_min = 0.5 financial_filter.filter_max = 50 financial_filter.stock_field = ft.StockField.CURRENT_RATIO financial_filter.is_no_filter = False financial_filter.sort = ft.SortDir.ASCEND # 多个筛选条件,只能有一个排序方向。 financial_filter.quarter = ft.FinancialQuarter.ANNUAL # 对香港市场的股票做简单和财务筛选 ret, ls = quote_ctx.get_stock_filter( market=ft.Market.HK, filter_list=[simple_filter, financial_filter]) if ret == ft.RET_OK: last_page, all_count, ret_list = ls print(len(ret_list), all_count, ret_list) for item in ret_list: print(item.stock_code) # 取股票代码 print(item.stock_name) # 取股票名称 print(item[simple_filter]) # 取 simple_filter 对应的变量值 print(item.cur_price) # 效果同上,也是取 simple_filter 对应的变量值 print(item[financial_filter]) # 取 financial_filter 对应的变量值 else: print('error: ', ls) quote_ctx.close() # 结束后记得关闭当条连接,防止连接条数用尽
def filterRSI(): import futu as ft import talib quote_ctx = ft.OpenQuoteContext(host='127.0.0.1', port=11111) quote_ctx.subscribe(['US.AMZN'], [ft.SubType.K_60M]) ret, df = quote_ctx.get_cur_kline('US.AMZN', 1000, ft.SubType.K_60M, ft.AuType.QFQ) quote_ctx.close() if ret == ft.RET_OK: df['rsi13'] = talib.RSI(df['close'], 13) # return data buyList = df[(df.rsi13 < 30)] buyList = addDateTime(buyList) # buyList_day = buyList.drop_duplicates('time_key_day', 'first') # for index, row in df[(df.rsi13 < 20)].iterrows(): # print(row['rsi13']) # df[len(df), :] return buyList;
def establish_connections(user_connection_type, unlock_trade=True, user_host='127.0.0.1', user_port=11111, user_is_encrypt=None, user_security_firm=SecurityFirm.FUTUINC): ''' Ingest: Pass in connection criterias Output: Initialized instance/object of either trade/quote ''' #Validate connection type connection_type_choices = ['trade', 'quote'] assert user_connection_type in connection_type_choices, \ f'connection type must be in {[choice for choice in connection_type_choices]}' try: #Intialized trading API if user_connection_type == 'trade': trader = ft.OpenUSTradeContext(host=user_host, port=user_port, is_encrypt=user_is_encrypt, security_firm=user_security_firm) #If user wants to unlock account, ask for password to unlock if unlock_trade == True: user_pass = getpass.getpass() #Log in first in order to pull account info trader.unlock_trade(password=user_pass, is_unlock=True) return trader #Initialize quote API elif user_connection_type == 'quote': quoter = ft.OpenQuoteContext(host=user_host, port=user_port, is_encrypt=user_is_encrypt) return quoter except Exception as e: raise e
def loop_get_mkt_snapshot(api_svr_ip, api_svr_port, market): """ 验证接口:获取某个市场的全部快照数据 get_mkt_snapshot :param api_svr_ip: (string)ip :param api_svr_port: (int)port :param market: market type :return: """ # 创建行情api quote_ctx = ft.OpenQuoteContext(host=api_svr_ip, port=api_svr_port) stock_type = [ ft.SecurityType.STOCK, ft.SecurityType.IDX, ft.SecurityType.ETF, ft.SecurityType.WARRANT, ft.SecurityType.BOND ] stock_codes = [] # 枚举所有的股票类型,获取股票codes for sub_type in stock_type: ret_code, ret_data = quote_ctx.get_stock_basicinfo(market, sub_type) if ret_code == 0: print( "get_stock_basicinfo: market={}, sub_type={}, count={}".format( market, sub_type, len(ret_data))) for ix, row in ret_data.iterrows(): stock_codes.append(row['code']) if len(stock_codes) == 0: quote_ctx.close() print("Error market:'{}' can not get stock info".format(market)) return # 按频率限制获取股票快照: 每5秒200支股票 for i in range(1, len(stock_codes), 200): print("from {}, total {}".format(i, len(stock_codes))) ret_code, ret_data = quote_ctx.get_market_snapshot(stock_codes[i:i + 200]) if ret_code != 0: print(ret_data) time.sleep(3) quote_ctx.close()
def _process_init_api(self): if type(self._quote_ctx) != int or type(self._trade_ctx) != int: return # 创建futu api对象 if self._quote_ctx == 0: self._quote_ctx = ft.OpenQuoteContext(self._api_ip, self._api_port) if self._trade_ctx == 0: if self._market == MARKET_HK: self._trade_ctx = ft.OpenHKTradeContext( self._api_ip, self._api_port) elif self._market == MARKET_US: self._trade_ctx = ft.OpenUSTradeContext( self._api_ip, self._api_port) else: raise Exception("error param!") if self._env_type == ft.TrdEnv.REAL: ret, _ = self._trade_ctx.unlock_trade(self._trade_password) if 0 != ret: raise Exception("error param!") # 开始futu api异步数据推送 self._quote_ctx.start() self._trade_ctx.start() # 市场状态检查 self._check_market_event = FutuMarketEvent(self._market, self._quote_ctx, self._event_engine) #定阅行情数据 self._futu_data_event = FutuDataEvent(self, self._quote_ctx, self._event_engine, self._tiny_strate.symbol_pools) # 启动事件 self._tiny_strate.on_start()
def get_all_market_plate_stock_rs(): # 获取时间戳 time_now = time.strftime("%Y%m%d", time.localtime(time.time())) # print(time_now) path = "./data/" + time_now + "/" # 如果路径存在着删除 if os.path.exists(path) is True: try: print("删除已存在路径") shutil.rmtree(path) except IOError as err: print("路径删除异常") os.mkdir(path) # 实例化行情上下文对象 quote_ctx = ft.OpenQuoteContext(host="127.0.0.1", port=11111) # quote_ctx = ft.OpenQuoteContext(host="118.25.176.152", port=11111) # 按市场获取四分位 # 按板块获取四分位 get_plate_stock_rs("HK", path, quote_ctx) # get_plate_stock_rs("SZ", path) # get_plate_stock_rs("SH", path) quote_ctx.close()
if __name__ == "__main__": # futubase() # saveToCsv() # csv = loadCsv() # df = addRSI() # df = filterRSI() # df import futu as ft quote_ctx = ft.OpenQuoteContext(host='127.0.0.1', port=11111) # subscribe Kline stock_code_list = ["US.AAPL", "HK.00700"] sub_type_list = [ft.ft.SubType.K_1M, ft.SubType.K_5M, ft.SubType.K_15M, ft.SubType.K_30M, ft.SubType.K_60M, ft.SubType.K_DAY, ft.SubType.K_WEEK, ft.SubType.K_MON] ret_status, ret_data = ft.quote_ctx.subscribe(stock_code_list, sub_type_list) if ret_status != ft.ft.RET_OK: print(ret_data) exit() ret_status, ret_data = ft.quote_ctx.query_subscription() if ret_status == ft.RET_ERROR: print(ret_data) exit() print(ret_data) for code in stock_code_list: for ktype in [ft.SubType.K_DAY, ft.SubType.K_1M, ft.SubType.K_5M]:
import futu as ft import time quote_ctx = ft.OpenQuoteContext(host="122.152.220.151", port=65111) code = 'SH.600000' code_list = ['SH.600000'] def get_now_price(): quote_ctx.subscribe(code_list, [ft.SubType.QUOTE]) data = quote_ctx.get_stock_quote(code_list) # print(data) # title = list(data[-1]) # print(title) print(list(data[-1].iloc[:, 8])) # print([i for i in list(data)]) # print(data) def get_max_volume(): quote_ctx.subscribe(code_list, [ft.SubType.RT_DATA]) for i in code_list: data = quote_ctx.get_rt_data(i) # index = list(data) print(data) # print(max(list(quote_ctx.get_rt_data(i)[-1].iloc[:, 7]))) # print(index) # 上下文控制 quote_ctx.start() # 开启异步数据接收
def __enter__(self): self.quote_ctx = ft.OpenQuoteContext(host="127.0.0.1", port=11111) self.quote_ctx.start() self.quote_ctx.set_handler(ft.TickerHandlerBase()) return self
# -*- coding: utf-8 -*- # 导入futu-api import futu as ft import pandas as pd pd.set_option('display.width', 2000) pd.set_option('display.max_colwidth', 100) pd.set_option('display.max_columns', 100) # 实例化行情上下文对象 quote_ctx = ft.OpenQuoteContext(host="100.66.37.76", port=8080) # 上下文控制 quote_ctx.start() # 开启异步数据接收 quote_ctx.set_handler(ft.TickerHandlerBase()) # 设置用于异步处理数据的回调对象(可派生支持自定义) # 低频数据接口 market = ft.Market.HK code = 'HK.800000' code_list = [code] # print(quote_ctx.get_trading_days(market, start=None, end=None)) # 获取交易日 # print(quote_ctx.get_stock_basicinfo(market, stock_type=ft.SecurityType.IDX)) # 获取股票信息 # # 高频数据接口 #quote_ctx.subscribe(code, [ft.SubType.TICKER, ft.SubType.K_DAY, ft.SubType.RT_DATA]) #quote_ctx.subscribe(code, [ft.SubType.QUOTE, ft.SubType.TICKER, ft.SubType.K_DAY, ft.SubType.ORDER_BOOK, ft.SubType.RT_DATA, ft.SubType.BROKER]) # print(quote_ctx.get_stock_quote(code)) # 获取报价 # print(quote_ctx.get_rt_ticker(code)) # 获取逐笔
def Init(): global quote_ctx quote_ctx = ft.OpenQuoteContext(host='127.0.0.1', port=11111) quote_ctx.start()
# 一个简单的追涨杀跌策略 import time import futu as ft list = [] quote_ctx = ft.OpenQuoteContext(host="10.0.30.140", port=11111) code = 'US.AAPL' # 选择标的 LENGTH = 12 # 样本容量 quote_ctx.subscribe(code, [ ft.SubType.QUOTE, ft.SubType.TICKER, ft.SubType.K_DAY, ft.SubType.ORDER_BOOK, ft.SubType.RT_DATA, ft.SubType.BROKER ]) # 实例化美股交易上下文对象 trade_us_ctx = ft.OpenUSTradeContext(host="10.0.30.140", port=11111) trade_us_ctx.unlock_trade(password='******') def doTicker(): print("开始执行追涨杀跌策略购买AAPL") last = quote_ctx.get_stock_quote(code) #获取最新报价 last_price = last[1].last_price if len(list) < LENGTH: list.append(last_price) #累加最近(=逐笔) else: pMax = max(list) # 取出最高价 pMin = min(list) # 取出最低价 if last_price > pMax: # 最新价是周期内的新高(追涨) account = trade_us_ctx.accinfo_query(trd_env=ft.TrdEnv.SIMULATE) print("buy " + str(account)) if account[1].power > last_price: # 资产足够(买1股) trade_us_ctx.place_order(price=last_price,
print('smart_sell 下单失败:{}'.format(data)) return None else: print('smart_sell 下单成功') print(data) return data if __name__ == "__main__": ip = '127.0.0.1' port = 11111 code = 'HK.00700' unlock_pwd = '123456' trd_env = ft.TrdEnv.SIMULATE order_type = ft.OrderType.NORMAL quote_ctx = ft.OpenQuoteContext(ip, port) trd_ctx = ft.OpenHKTradeContext(ip, port) quote_ctx.subscribe(code, ft.SubType.ORDER_BOOK) if trd_env == ft.TrdEnv.REAL: print("* unlock_trade:{}".format(trd_ctx.unlock_trade(unlock_pwd))) # simple_sell(quote_ctx, trd_ctx, code, 380.0, 100, trd_env, order_type) smart_sell(quote_ctx, trd_ctx, code, 2600, trd_env, order_type) # smart_buy(quote_ctx, trd_ctx, code, 1000, trd_env, order_type) # quote_ctx.close() # trd_ctx.close()
print(_stock) # 回调逻辑处理 class StockQuoteMonitor(ft.StockQuoteHandlerBase): def on_recv_rsp(self, rsp_str): ret_code, data = super(StockQuoteMonitor, self).on_recv_rsp(rsp_str) if ret_code != ft.RET_OK: print("StockQuoteMonitor: error, msg: %s" % data) return ft.RET_ERROR, data notify(data) return ft.RET_OK, data # 实例化行情上下文对象 quote_ctx = ft.OpenQuoteContext(host="127.0.0.1", port=11111) # 上下文控制 # 开启异步数据接收 quote_ctx.start() # 设置用于异步处理数据的回调对象(可派生支持自定义) quote_ctx.set_handler(ft.TickerHandlerBase()) # 注册实时报价handder quote_ctx.set_handler(StockQuoteMonitor()) # 实时报价 quote_ctx.subscribe(stock, [ft.SubType.QUOTE]) while True:
def __init__(self): self.quote_ctx = ft.OpenQuoteContext(host='127.0.0.1', port=11111) import mytool fsw_obj = mytool.FindStockWarrent(self.quote_ctx, "HK.800000") bear_list_800000, bull_list_800000 = fsw_obj.get_best_warrant() fsw_obj = mytool.FindStockWarrent(self.quote_ctx, "HK.00700") bear_list_00700, bull_list_00700 = fsw_obj.get_best_warrant() std_obj = SaveTickData(stock_code="HK.800000") std_obj.create_warrant_table() std_obj.save_data_warrant(bull_list_800000, bear_list_800000) std_obj = SaveTickData(stock_code="HK.00700") std_obj.create_warrant_table() std_obj.save_data_warrant(bull_list_00700, bear_list_00700) self.symbol_pools = ['HK.00700', 'HK.800000'] self.data_queue_dict = {} for i in range(3): if bear_list_800000[i]: self.symbol_pools.append(json.loads(bear_list_800000[i])['stock']) if bull_list_800000[i]: self.symbol_pools.append(json.loads(bull_list_800000[i])['stock']) if bear_list_00700[i]: self.symbol_pools.append(json.loads(bear_list_00700[i])['stock']) if bull_list_00700[i]: self.symbol_pools.append(json.loads(bull_list_00700[i])['stock']) self.log("get symbol list is %s" % self.symbol_pools) for symbol in self.symbol_pools: self.data_queue_dict[symbol] = multiprocessing.Manager().Queue() class QuoteHandler(ft.StockQuoteHandlerBase): """报价处理器""" futu_data_event = self def on_recv_rsp(self, rsp_str): ret_code, content = super(QuoteHandler, self).on_recv_rsp(rsp_str) if ret_code != ft.RET_OK: return ft.RET_ERROR, content self.futu_data_event.process_quote(content) return ft.RET_OK, content class OrderBookHandler(ft.OrderBookHandlerBase): """摆盘处理器""" futu_data_event = self def on_recv_rsp(self, rsp_str): ret_code, content = super(OrderBookHandler, self).on_recv_rsp(rsp_str) if ret_code != ft.RET_OK: return ft.RET_ERROR, content self.futu_data_event.process_orderbook(content) return ft.RET_OK, content class TickerHandler(ft.TickerHandlerBase): """逐笔数据处理器""" futu_data_event = self def on_recv_rsp(self, rsp_str): ret_code, content = super(TickerHandler, self).on_recv_rsp(rsp_str) if ret_code != ft.RET_OK: return ft.RET_ERROR, content self.futu_data_event.process_tick(content) return ft.RET_OK, content class RTDataHandler(ft.RTDataHandlerBase): """分时数据处理器""" futu_data_event = self def on_recv_rsp(self, rsp_str): ret_code, content = super(RTDataHandler, self).on_recv_rsp(rsp_str) if ret_code != ft.RET_OK: return ft.RET_ERROR, content self.futu_data_event.process_rt(content) return ft.RET_OK, content class CurKlineHandler(ft.CurKlineHandlerBase): """实时k线推送处理器""" futu_data_event = self def on_recv_rsp(self, rsp_str): ret_code, content = super(CurKlineHandler, self).on_recv_rsp(rsp_str) if ret_code != ft.RET_OK: return ft.RET_ERROR, content self.futu_data_event.process_curkline(content) return ft.RET_OK, content # 设置回调处理对象 self.quote_ctx.set_handler(QuoteHandler()) self.quote_ctx.set_handler(OrderBookHandler()) #self.quote_ctx.set_handler(CurKlineHandler()) self.quote_ctx.set_handler(TickerHandler()) self.quote_ctx.set_handler(RTDataHandler()) # 定阅数据 subtype_list = [ft.SubType.QUOTE, ft.SubType.ORDER_BOOK, ft.SubType.TICKER, ft.SubType.RT_DATA] ret, data = self.quote_ctx.subscribe(self.symbol_pools, subtype_list) if ret != ft.RET_OK: raise Exception('订阅行情失败:{}'.format(data))
for ktype in [ft.SubType.K_WEEK]: # ft.SubType.K_15M, ft.SubType.K_1M ret_code, ret_data = quote_ctx.get_cur_kline(code, 1000, ktype) if ret_code == ft.RET_ERROR : print(code, ktype, ret_data) exit() if ret_data.empty: continue kline_table = ret_data print("%s KLINE %s" % (code, ktype)) kline_table['rsi13'] = talib.RSI(kline_table['close'], RSI_NUM) b = kline_table.iloc[-1] # b.at["note"] = b.code + ' ' + str(b.close) + ': rsi13(' + ktype + ') ' + str(round(b.rsi13)) b.at["note"] = '{:<8} {:<9.2f} {:<9.2f}'.format(b.code, b.rsi13, b.close) # print(kline_table) # print("\n\n") resultList.append(b) outputMessage = 'RSI update: \n{:<6} {:<11} {:<4}\n'.format('Code', 'rsi'+str(RSI_NUM)+str(ktype[2:]), 'close') for i in resultList: outputMessage += i.note + '\n' print(""+outputMessage) ckTelegram().send_message_group(outputMessage) # ckTelegram().send_message_ck(outputMessage) if __name__ == "__main__": quote_ctx = ft.OpenQuoteContext() _example_cur_kline(quote_ctx) quote_ctx.close()