def pplot_from_df(df, kind='line', stock=False, y_axes=None, debug=False, **kwargs): """ :param df: (pd.DataFrame): Column names become series names :param kind: (str or list): Use list of same length as number of cols for multiple plot types (e.g. ['line_w_col', 'column']) :param stock: :param y_axes: :param debug: (bool): Pretty prints options json :param kwargs: (): Plotting options such as resolution, labels, color, etc. :return: """ # If series given instead of DataFrame, convert: df = pd.DataFrame(df) # If no columns, do nothing: if df.shape[1] == 0: print("nothing to plot...") return # Create a color list for each line to plot: if 'colors' not in kwargs: kwargs['colors'] = map( lambda val: val.get_hex_l(), list(Color('#1492FB').range_to(Color('#27662A'), df.shape[1])) ) # Set y axis if y_axes is None: y_axes = [1] * df.shape[1] else: assert (len(y_axes) == df.shape[1]), "y_axes must be list of same length as dataframe columns" # Should also assert something about the values in this list... later # Create highcharts_df object: # (Use height and width if provided): if stock: hc_visualization = Highstock(**{key: kwargs.pop(key) for key in ['width', 'height'] if key in kwargs}) else: hc_visualization = Highchart(**{key: kwargs.pop(key) for key in ['width', 'height'] if key in kwargs}) # Set timeseries encoding automatically: if df.index.is_all_dates: # NOTE *** AFTER monthes, I finally figured out that certain types of option settings # were the cause of time not encoding properly. Basically, customer jinja-js like {x.point} functions # need to be created carefully with timestamps in mind. Also, data must be encoded as 32 bit datetime. # (e.g. df.index.map(lambda dt: dt.to_datetime()), or [(datetime.datetime(2016,9,28), $val), ...] hc_visualization.set_options('xAxis', {'type': 'datetime'}) # Set options (chart customization): options = get_highchart_options(**kwargs) if kind == 'line': for col_idx, col in enumerate(df.columns): hc_visualization = _highcharts_add_data_set(hc_visualization, df[col], col, kind, y_axes[col_idx]) elif kind == 'bar' or kind == 'column': # Add bar categories (dataframe index): options['xAxis']['categories'] = list(df.index) # Add grouped column/bar data: for col_idx, col in enumerate(df.columns): hc_visualization = _highcharts_add_data_set(hc_visualization, df[col], col, kind, y_axes[col_idx]) elif isinstance(kind, list): # Make sure the kind list is the right size: assert len(kind) == df.shape[1], "list kind must be the same length as df" # If columns in the list, map to line_w_col: if 'bar' in kind or 'column' in kind: kind = map(lambda a_kind: ("%s_w_col" % a_kind) if a_kind == 'line' else a_kind, kind) # Add categories: options['xAxis']['categories'] = list(df.index.values) # Add grouped data: for col_idx, col in enumerate(df.columns): hc_visualization = _highcharts_add_data_set(hc_visualization, df[col], col, kind[col_idx], y_axes[col_idx]) # Set options: hc_visualization.set_dict_options(options) # Print options json if debug mode is on: if debug: pp = pprint.PrettyPrinter(indent=1) pp.pprint(options) return hc_visualization
def main(argv): from highcharts import Highstock # 暂时这样避免其他脚本 import 出错 unittest() opts, args = parse_options(argv) #exchanges = ('binance', 'huobipro', 'okex', 'zb') #symbol = 'qtum/btc' #sdt = '2018-01-20 18-00-00' #edt = '2018-01-20 18-59-00' #folder = r'C:\Users\Eph\Desktop\CC\trade\ccxtbot\CCMarkets\data' exchanges = args symbol = opts.get('symbol') sdt = opts.get('start') edt = opts.get('stop') folder = opts.get('folder') prec = int(opts.get('prec', 8)) fname = opts.get('file', 'StockChart') verbose = opts.get('verbose', False) if not exchanges or not symbol or not sdt or not edt or not folder: usage(argv[0]) return 2 options = { 'chart': { 'height': '50%', # default None }, 'title': { 'text': 'Price Difference', }, "tooltip": { "xDateFormat": "%Y-%m-%d %H:%M:%S %A", # NOTE: BUG, 设置不生效 'pointFormat': '<span style="color:{point.color}">' + '\\u25CF'.decode('unicode-escape') + \ '</span> {series.name}: <b>{point.y}</b><br/>', 'padding': 1, # default 8 }, "legend": { "enabled": True }, "xAxis": { "type": "datetime" }, 'yAxis': { 'title': { 'text': '价格', }, 'opposite': True, # False 表示在左边显示,默认值为 True }, # 这是K线图的属性,不画K线图的话不需要 "plotOptions": { "candlestick": { "color": "#d75442", "upColor": "#6ba583" } }, "rangeSelector": { "buttons": [ { "type" : "hour", "count" : 1, "text" : "1h", }, { "type" : 'hour', "count" : 3, "text" : "3h" }, { "type" : "hour", "count" : 6, "text" : "6h" }, { "type" : "hour", "count" : 12, "text" : "12h" }, { "type" : "all", "text" : "All" } ], #"selected": 2, # 默认选择的索引号,从0开始,默认值为 undefined "inputEnabled": True, "inputBoxWidth": 150, # default 90 'inputDateFormat': '%Y/%m/%d %H:%M:%S', 'inputEditDateFormat': '%Y/%m/%d %H:%M:%S', }, } chart = Highstock() chart.set_options('global', {'timezoneOffset': -8 * 60}) chart.set_dict_options(options) #chart.set_options('chart', {'height': None}) chart.set_options( 'tooltip', { #'pointFormat': '<span style="color:{point.color}">' + '\\u25CF'.decode('unicode-escape') + \ #'</span> {series.name}: <b>{point.y:.%df}</b><br/>' % prec, 'valueDecimals': prec, 'valueSuffix': ' ' + symbol.replace('/', '_').upper().split('_')[1], }) ers = [] stats = {} for exchange in exchanges: inst = ExchangeRecords(exchange, symbol, sdt, edt, folder) ers.append(inst) stats[exchange] = {} stats[exchange]['records_count'] = 0 chart.set_options('subtitle', {'text': ers[0].symbol.replace('_', '/')}) # 'binance': {'Buy': x, 'Sell': y} all_records = {} loop_count = 0 # 标记哪个交易所已经拿完数据了 # {exchange: True/False, ...} ctl = {} for inst in ers: ctl[inst.exchange] = False while True: all_true = True for v in ctl.itervalues(): if not v: all_true = False break if ctl and all_true: break loop_count += 1 for inst in ers: record = inst.get_one_record() if record is None: ctl[inst.exchange] = True continue records_dict = all_records.setdefault(inst.exchange, {}) if not record: #ctl[inst.exchange] = True continue stats[inst.exchange]['records_count'] += 1 # 不需要小数点 t = int(int(float(record[0])) * 1000) #t += 3600*1000*8 # GMT+8 buy = records_dict.setdefault('buy', []) buy.append([t, float(record[1])]) sell = records_dict.setdefault('sell', []) sell.append([t, float(record[2])]) last = records_dict.setdefault('last', []) last.append([t, float(record[3])]) if verbose: print('loop_count:', loop_count) Log(json.dumps(stats, indent=4, sort_keys=True)) for exchange in exchanges: records_dict = all_records[exchange] chart.add_data_set(records_dict['buy'], series_type='line', name='%s buy' % exchange) chart.add_data_set(records_dict['sell'], series_type='line', name='%s sell' % exchange) chart.add_data_set(records_dict['last'], series_type='line', name='%s last' % exchange) # 后缀名值 .html chart.save_file(filename=fname) Log('Successfully write to the file:', fname + '.html')