def __init__(self) -> None: if self.start_timestamp: self.start_timestamp = to_pd_timestamp(self.start_timestamp) self.start_timestamp = self.trading_level.floor_timestamp(self.start_timestamp) self.current_timestamp = self.start_timestamp else: self.start_timestamp = now_pd_timestamp() if self.end_timestamp: self.end_timestamp = to_pd_timestamp(self.end_timestamp) self.security_type, self.exchange, self.code = decode_security_id(self.security_id) self.kdata_schema = get_kdata_schema(self.security_type) # init history data for model in self.models: datas = \ get_kdata(self.security_id, level=model.trading_level, end_timestamp=self.start_timestamp, order=self.kdata_schema.timestamp.desc(), limit=model.history_size) if datas: model.init_history_data(datas) if not datas: self.logger.warning( "to {}, {} no history data ".format(self.start_timestamp, self.security_id)) elif len(datas) < self.history_data_size: self.logger.warning( "to {}, {} history data size:{}".format(self.start_timestamp, self.security_id, len(datas)))
def draw_kline(df_list: List[pd.DataFrame], render='html', file_name=None) -> Kline: kline = None for df in df_list: security_id = df['security_id'][0] security_type, _, _ = decode_security_id(security_id) xdata = [to_time_str(timestamp) for timestamp in df.index] if security_type == SecurityType.stock: ydata = df.loc[:, ['qfq_open', 'qfq_close', 'qfq_low', 'qfq_high' ]].values.tolist() else: ydata = df.loc[:, ['open', 'close', 'low', 'high']].values.tolist() current_kline = get_default_kline() current_kline.add_xaxis(xdata) current_kline.add_yaxis(security_id, ydata, itemstyle_opts=opts.ItemStyleOpts( color="#ec0000", color0="#00da3c", border_color="#8A0000", border_color0="#008F28")) if not kline: kline = current_kline else: kline.overlap(current_kline) if render == 'html': kline.render(get_ui_path(file_name)) return kline
def get_kdata(security_id, level=TradingLevel.LEVEL_1DAY.value, provider='eastmoney', columns=None, return_type='df', start_timestamp=None, end_timestamp=None, filters=None, session=None, order=None, limit=None): security_type, exchange, code = decode_security_id(security_id) data_schema = get_kdata_schema(security_type, level=level) return get_data(data_schema=data_schema, security_id=security_id, level=level, provider=provider, columns=columns, return_type=return_type, start_timestamp=start_timestamp, end_timestamp=end_timestamp, filters=filters, session=session, order=order, limit=limit)
def get_trading_signals_figure(order_reader: OrderReader, security_id: str, provider: Union[str, Provider], level): security_type, _, _ = decode_security_id(security_id) security_factor = TechnicalFactor(security_type=security_type, security_list=[security_id], level=level, provider=provider) if df_is_not_null(security_factor.get_data_df()): print(security_factor.get_data_df().tail()) # generate the annotation df order_reader.move_on(timeout=0) df = order_reader.get_data_df().copy() if df_is_not_null(df): df['value'] = df['order_price'] df['flag'] = df['order_type'].apply(lambda x: order_type_flag(x)) df['color'] = df['order_type'].apply(lambda x: order_type_color(x)) print(df.tail()) data, layout = security_factor.draw(render=None, figures=go.Candlestick, annotation_df=df) return go.Figure(data=data, layout=layout)
def could_short(security_type=None, security_id=None): if security_type is None: security_type, _, _ = decode_security_id(security_id) if security_type == SecurityType.coin: return True if security_type == SecurityType.stock: return False
def get_trading_t(security_type=None, security_id=None): if security_type is None: security_type, _, _ = decode_security_id(security_id) if security_type == SecurityType.coin: return 0 if security_type == SecurityType.stock: return 1
def on_trading_close(self, timestamp): self.logger.info('on_trading_close:{}'.format(timestamp)) self.latest_account['value'] = 0 self.latest_account['all_value'] = 0 for position in self.latest_account['positions']: # use qfq for stock security_type, _, _ = decode_security_id(position['security_id']) data_schema = get_kdata_schema(security_type, level=self.level) kdata = get_kdata(provider=self.provider, level=self.level, security_id=position['security_id'], order=data_schema.timestamp.desc(), end_timestamp=timestamp, limit=1) # use qfq for stock if security_type == SecurityType.stock: closing_price = kdata['qfq_close'][0] else: closing_price = kdata['close'][0] position['available_long'] = position['long_amount'] position['available_short'] = position['short_amount'] if closing_price: if (position['long_amount'] is not None) and position['long_amount'] > 0: position['value'] = position['long_amount'] * closing_price self.latest_account['value'] += position['value'] elif (position['short_amount'] is not None) and position['short_amount'] > 0: position['value'] = 2 * (position['short_amount'] * position['average_short_price']) position[ 'value'] -= position['short_amount'] * closing_price self.latest_account['value'] += position['value'] else: self.logger.warning( 'could not refresh close value for position:{},timestamp:{}' .format(position['security_id'], timestamp)) # remove the empty position self.latest_account['positions'] = [ position for position in self.latest_account['positions'] if position['long_amount'] > 0 or position['short_amount'] > 0 ] self.latest_account['all_value'] = self.latest_account[ 'value'] + self.latest_account['cash'] self.latest_account['closing'] = True self.latest_account['timestamp'] = to_pd_timestamp(timestamp) self.logger.info('on_trading_close:{},latest_account:{}'.format( timestamp, self.latest_account)) self.persist_account(timestamp)
def get_plotly_data(self): if not df_is_not_null(self.get_data_df()): return [] df_list: List[pd.DataFrame] = [] for _, df_item in self.get_data_df().groupby(self.category_field): df = df_item.copy() df.reset_index(inplace=True, level=self.category_field) df_list.append(df) if len(df_list) > 1: df_list = fill_with_same_index(df_list=df_list) data = [] for df in df_list: series_name = df[df[self.category_field].notna()][ self.category_field][0] xdata = [timestamp for timestamp in df.index] # draw all figures for one category for i, figure in enumerate(self.figures): if figure == go.Candlestick: security_type, _, _ = decode_security_id(series_name) trace_name = '{}_kdata'.format(series_name) if security_type == SecurityType.stock: open = df.loc[:, 'qfq_open'] close = df.loc[:, 'qfq_close'] high = df.loc[:, 'qfq_high'] low = df.loc[:, 'qfq_low'] else: open = df.loc[:, 'open'] close = df.loc[:, 'close'] high = df.loc[:, 'high'] low = df.loc[:, 'low'] data.append( go.Candlestick(x=xdata, open=open, close=close, low=low, high=high, name=trace_name)) else: trace_name = '{}_{}'.format(series_name, self.value_fields[i]) ydata = df.loc[:, self.value_fields[i]].values.tolist() data.append( figure(x=xdata, y=ydata, mode=self.modes[i], name=trace_name)) return data
def get_trading_meta(security_id=None, security_type=None, exchange=None): if security_id: security_type, exchange, _ = decode_security_id(security_id) if security_type == SecurityType.future: return {'trading_t': 0, 'could_short': True} if security_type == SecurityType.coin: return {'trading_t': 0, 'could_short': True} if security_type == SecurityType.stock: return {'trading_t': 1, 'could_short': False}
def get_close_column(security_id): security_type, _, _ = decode_security_id(security_id) data_schema = get_kdata_schema(security_type) if security_type == SecurityType.stock: columns = [ data_schema.security_id, data_schema.timestamp, data_schema.qfq_close ] else: columns = [ data_schema.security_id, data_schema.timestamp, data_schema.close ] return columns
def draw_kline(df_list: List[pd.DataFrame]) -> Kline: kline = None for df in df_list: print(df) security_id = df['security_id'][0] security_type, _, _ = decode_security_id(security_id) xdata = [to_time_str(timestamp) for timestamp in df.index] if security_type == SecurityType.stock: ydata = df.loc[:, ['open', 'close', 'low', 'high']].values.tolist() else: ydata = df.loc[:, ['open', 'close', 'low', 'high']].values.tolist() current_kline = ( Kline() .add_xaxis(xdata) .add_yaxis( security_id, ydata, itemstyle_opts=opts.ItemStyleOpts( color="#ec0000", color0="#00da3c", border_color="#8A0000", border_color0="#008F28", ), ) .set_global_opts( xaxis_opts=opts.AxisOpts(is_scale=True), yaxis_opts=opts.AxisOpts( is_scale=True, splitarea_opts=opts.SplitAreaOpts( is_show=True, areastyle_opts=opts.AreaStyleOpts(opacity=1) ), ), datazoom_opts=[opts.DataZoomOpts()], title_opts=opts.TitleOpts(title="Kline-ItemStyle"), ) ) if not kline: kline = current_kline else: kline.overlap(current_kline) return kline
def get_trader_details(account_reader: AccountReader, order_reader: OrderReader, provider: Union[str, Provider]): graph_list = [] account_data, account_layout = account_reader.draw(render=None, value_field='all_value', keep_ui_state=False) for trader_name in account_reader.trader_names: graph_list.append( dcc.Graph(id='{}_account'.format(trader_name), figure={ 'data': account_data, 'layout': account_layout })) df_account = account_reader.get_data_df() if df_is_not_null(df_account): df_orders = order_reader.get_data_df() if df_is_not_null(df_orders): grouped = df_orders.groupby('security_id') for security_id, order_df in grouped: security_type, _, _ = decode_security_id(security_id) security_factor = TechnicalFactor(security_type=security_type, security_list=[security_id], level=account_reader.level, provider=provider) if df_is_not_null(security_factor.get_data_df()): print(security_factor.get_data_df().tail()) data, layout = security_factor.draw(figure=go.Candlestick, render=None, keep_ui_state=False) graph_list.append( dcc.Graph(id='{}_signals'.format(security_id), figure={ 'data': data, 'layout': layout })) return graph_list
def on_trading_signal(self, trading_signal: TradingSignal): self.logger.info('trader:{} received trading signal:{}'.format( self.trader_name, trading_signal)) security_id = trading_signal.security_id current_timestamp = trading_signal.the_timestamp order_type = AccountService.trading_signal_to_order_type( trading_signal.trading_signal_type) trading_level = trading_signal.trading_level.value if order_type: try: kdata = get_kdata(provider=self.provider, security_id=security_id, level=trading_level, start_timestamp=current_timestamp, end_timestamp=current_timestamp, limit=1) if kdata is not None and not kdata.empty: # use qfq for stock security_type, _, _ = decode_security_id( kdata['security_id'][0]) if security_type == SecurityType.stock: the_price = kdata['qfq_close'][0] else: the_price = kdata['close'][0] if the_price: self.order(security_id=security_id, current_price=the_price, current_timestamp=current_timestamp, order_pct=trading_signal.position_pct, order_money=trading_signal.order_money, order_type=order_type) else: self.logger.warning( 'ignore trading signal,wrong kdata,security_id:{},timestamp:{},kdata:{}' .format(security_id, current_timestamp, kdata.to_dict(orient='records'))) else: self.logger.warning( 'ignore trading signal,could not get kdata,security_id:{},timestamp:{}' .format(security_id, current_timestamp)) except Exception as e: self.logger.exception(e)
def get_current_price(security_list=None, security_type=SecurityType.coin): result = {} if security_type == SecurityType.coin: if security_list: for security_id in security_list: a, exchange, code = decode_security_id(security_id) assert SecurityType(a) == security_type ccxt_exchange = CCXTAccount.get_ccxt_exchange( exchange_str=exchange) if not ccxt_exchange: raise Exception('{} not support'.format(exchange)) orderbook = ccxt_exchange.fetch_order_book(code) bid = orderbook['bids'][0][0] if len( orderbook['bids']) > 0 else None ask = orderbook['asks'][0][0] if len( orderbook['asks']) > 0 else None security_id = f'coin_{exchange}_{code}' result[security_id] = (bid, ask) return result
def common_draw(df_list: List[pd.DataFrame], chart_type=Line, columns=[]): charts = None for df in df_list: print(df) security_id = df['security_id'][0] security_type, _, _ = decode_security_id(security_id) xdata = [to_time_str(timestamp) for timestamp in df.index] ydata = df.loc[:, columns].values.tolist() current_chart = None if chart_type == Line: current_chart = Line() current_chart.add_xaxis(xdata) current_chart.add_yaxis(security_id, ydata, is_smooth=True) current_chart.set_global_opts(title_opts=opts.TitleOpts(title="Line-smooth")) if not charts: charts = current_chart else: charts.overlap(current_chart) return charts
def draw_kline(df_list: List[pd.DataFrame], markpoints_list: List[pd.DataFrame] = None, render='html', file_name=None) -> Kline: if len(df_list) > 1: df_list = fill_with_same_index(df_list=df_list) kline = None for idx, df in enumerate(df_list): security_id = df[df.security_id.notna()]['security_id'][0] security_type, _, _ = decode_security_id(security_id) xdata = [to_time_str(timestamp) for timestamp in df.index] if security_type == SecurityType.stock: ydata = df.loc[:, ['qfq_open', 'qfq_close', 'qfq_low', 'qfq_high']].values.tolist() else: ydata = df.loc[:, ['open', 'close', 'low', 'high']].values.tolist() current_kline = get_default_kline() current_kline.add_xaxis(xdata) # markpoint markpoint_opts = None if markpoints_list: mark_points = markpoints_list[idx] if mark_points is not None and not mark_points.empty: mark_point_items = [] for timestamp, item in mark_points.iterrows(): if to_time_str(timestamp) in df.index: if item['order_type'] == 'order_long': flag_name = 'buy' symbol = 'arrow' color = "#ec0000" if item['order_type'] == 'order_close_long': flag_name = 'sell' symbol = 'pin' color = "#00da3c" value = round(item['order_price'], 2) mark_point_items.append( opts.MarkPointItem(name=flag_name, coord=[to_time_str(timestamp), value], value=value, symbol=symbol, symbol_size=20)) markpoint_opts = opts.MarkPointOpts(data=mark_point_items, symbol_size=20) current_kline.add_yaxis(security_id, ydata, markpoint_opts=markpoint_opts, itemstyle_opts=opts.ItemStyleOpts( color="#ec0000", color0="#00da3c", border_color="#8A0000", border_color0="#008F28")) if not kline: kline = current_kline else: kline.overlap(current_kline) if render == 'html': kline.render(get_ui_path(file_name)) elif render == 'notebook': kline.render_notebook() return kline
def get_trader_detail_figures(trader_domain: business.Trader, account_reader: AccountReader, order_reader: OrderReader): graph_list = [] if account_reader: account_data, account_layout = account_reader.draw( render=None, value_fields=['all_value'], keep_ui_state=False) for trader_name in account_reader.trader_names: graph_list.append( dcc.Graph(id='{}-account'.format(trader_name), figure={ 'data': account_data, 'layout': account_layout })) order_reader.move_on(timeout=0) df_orders = order_reader.get_data_df().copy() if df_is_not_null(df_orders): grouped = df_orders.groupby('security_id') for security_id, order_df in grouped: security_type, _, _ = decode_security_id(security_id) indicators = [] indicators_param = [] indicator_cols = [] if trader_domain.technical_factors: tech_factors = simplejson.loads( trader_domain.technical_factors) for factor in tech_factors: indicators += factor['indicators'] indicators_param += factor['indicators_param'] indicator_cols += factor['indicator_cols'] security_factor = TechnicalFactor( security_type=security_type, security_list=[security_id], start_timestamp=trader_domain.start_timestamp, end_timestamp=trader_domain.end_timestamp, level=trader_domain.level, provider=trader_domain.provider, indicators=indicators, indicators_param=indicators_param) # generate the annotation df df = order_df.copy() if df_is_not_null(df): df['value'] = df['order_price'] df['flag'] = df['order_type'].apply( lambda x: order_type_flag(x)) df['color'] = df['order_type'].apply( lambda x: order_type_color(x)) print(df.tail()) data, layout = security_factor.draw_with_indicators( render=None, annotation_df=df, indicators=indicator_cols, height=620) if trader_domain.real_time: result = get_current_price(security_list=[security_id]) bid_ask = result.get(security_id) if bid_ask: graph_list.append( daq.LEDDisplay(id='ask', label=f'ask price', value=bid_ask[0], color="#00da3c")) graph_list.append( daq.LEDDisplay(id='bid', label=f'bid price', value=bid_ask[1], color="#FF5E5E")) graph_list.append( dcc.Graph(id='{}-{}-signals'.format(trader_domain.trader_name, security_id), figure={ 'data': data, 'layout': layout })) return graph_list
def get_trader_detail_figures(trader_domain: business.Trader, account_reader: AccountReader, order_reader: OrderReader): graph_list = [] account_data, account_layout = account_reader.draw( render=None, value_fields=['all_value'], keep_ui_state=False) for trader_name in account_reader.trader_names: graph_list.append( dcc.Graph(id='{}-account'.format(trader_name), figure={ 'data': account_data, 'layout': account_layout })) df_orders = order_reader.get_data_df() if df_is_not_null(df_orders): grouped = df_orders.groupby('security_id') for security_id, order_df in grouped: security_type, _, _ = decode_security_id(security_id) # TODO:just show the indicators used by the trader security_factor = TechnicalFactor( security_type=security_type, security_list=[security_id], start_timestamp=trader_domain.start_timestamp, end_timestamp=trader_domain.end_timestamp, level=trader_domain.level, provider=trader_domain.provider, indicators=['ma', 'ma'], indicators_param=[{ 'window': 5 }, { 'window': 10 }]) # if df_is_not_null(security_factor.get_data_df()): # print(security_factor.get_data_df().tail()) # generate the annotation df order_reader.move_on(timeout=0) df = order_reader.get_data_df().copy() if df_is_not_null(df): df['value'] = df['order_price'] df['flag'] = df['order_type'].apply( lambda x: order_type_flag(x)) df['color'] = df['order_type'].apply( lambda x: order_type_color(x)) print(df.tail()) data, layout = security_factor.draw_with_indicators( render=None, annotation_df=df) graph_list.append( dcc.Graph(id='{}-{}-signals'.format(trader_domain.trader_name, security_id), figure={ 'data': data, 'layout': layout })) return graph_list
def __init__(self, security_list: List[str] = None, exchanges: List[str] = ['sh', 'sz'], codes: List[str] = None, start_timestamp: Union[str, pd.Timestamp] = None, end_timestamp: Union[str, pd.Timestamp] = None, provider: Union[str, Provider] = Provider.JOINQUANT, level: Union[str, TradingLevel] = TradingLevel.LEVEL_1DAY, trader_name: str = None, real_time: bool = False, kdata_use_begin_time: bool = False) -> None: assert self.security_type is not None if trader_name: self.trader_name = trader_name else: self.trader_name = type(self).__name__.lower() self.trading_signal_listeners = [] self.state_listeners = [] self.selectors: List[TargetSelector] = [] self.security_list = security_list self.exchanges = exchanges self.codes = codes # FIXME:handle this case gracefully if self.security_list: security_type, exchange, code = decode_security_id(self.security_list[0]) if not self.security_type: self.security_type = security_type if not self.exchanges: self.exchanges = [exchange] self.provider = Provider(provider) # make sure the min level selector correspond to the provider and level self.level = TradingLevel(level) self.real_time = real_time if start_timestamp and end_timestamp: self.start_timestamp = to_pd_timestamp(start_timestamp) self.end_timestamp = to_pd_timestamp(end_timestamp) else: assert False if real_time: logger.info( 'real_time mode, end_timestamp should be future,you could set it big enough for running forever') assert self.end_timestamp >= now_pd_timestamp() self.kdata_use_begin_time = kdata_use_begin_time self.account_service = SimAccountService(trader_name=self.trader_name, timestamp=self.start_timestamp, provider=self.provider, level=self.level) self.add_trading_signal_listener(self.account_service) self.init_selectors(security_list=security_list, security_type=self.security_type, exchanges=self.exchanges, codes=self.codes, start_timestamp=self.start_timestamp, end_timestamp=self.end_timestamp) self.selectors_comparator = self.init_selectors_comparator() self.trading_level_asc = list(set([TradingLevel(selector.level) for selector in self.selectors])) self.trading_level_asc.sort() self.trading_level_desc = list(self.trading_level_asc) self.trading_level_desc.reverse() self.targets_slot: TargetsSlot = TargetsSlot() self.session = get_db_session('zvt', StoreCategory.business) trader = get_trader(session=self.session, trader_name=self.trader_name, return_type='domain', limit=1) if trader: self.logger.warning("trader:{} has run before,old result would be deleted".format(self.trader_name)) self.session.query(business.Trader).filter(business.Trader.trader_name == self.trader_name).delete() self.session.commit() self.on_start()