Chart for serious stocks
        輸出 Google Chart 圖表。
        s = 資料筆數
        size = 圖表寬度、高度 [寬度,高度]
        candle = K 棒的寬度
332882
def gchart(self, s = 0, size = [], candle = 20):
    
    if s == 0:
      s = len(self.raw_data)
    if len(size) == 2:
      sw,sh = size
    else:
      sh = 300
      sw = 25 * s
      if sw > 1000:
        sw = 1000
        candle = 950/s

    stc = ''
    for i in self.raw_data[-s:]:
      stc += str(i) + ','
    sto = ''
    for i in self.stock_open[-s:]:
      sto += str(i) + ','
    sth = ''
    for i in self.stock_h[-s:]:
      sth += str(i) + ','
    stl = ''
    for i in self.stock_l[-s:]:
      stl += str(i) + ','
    stdate = ''
    for i in self.data_date[-s:]:
      stdate += str(i[-2:]) + '|'

    stmax = max(self.stock_h[-s:])
    stmin = min(self.stock_l[-s:])
    strange = (stmax-stmin) / 10

    re = "http://%(rand)s.chart.apis.google.com/chart?chs=%(sw)sx%(sh)s&cht=lc&chd=t1:0,0,0|0,%(h)s0|0,%(c)s0|0,%(o)s0|0,%(l)s0&chm=F,,1,1:-1,%(candle)s&chxt=y,x&chds=%(min)s,%(max)s&chxr=0,%(min)s,%(max)s,%(range)s&chg=20,%(chg)s&chtt=%(chtt)s&chxl=1:||%(chxl)s" % {
      'h': sth,
      'c': stc,
      'o': sto,
      'l': stl,
      'min': stmin,
      'max': stmax,
      'sw': sw,
      'sh': sh,
      'range': strange,
      'candle': candle,
      'chg': 10,
      'rand': random.randint(0,9),
      'chxl': stdate,
      'chtt': '%s %s' % (self.stock_name,self.stock_no)
    }
    return re
948763
function Edge(n1, n2, dataIndex) {

    /**
     * 节点1，如果是有向图则为源节点
     * @type {module:echarts/data/Graph.Node}
     */
    this.node1 = n1;

    /**
     * 节点2，如果是有向图则为目标节点
     * @type {module:echarts/data/Graph.Node}
     */
    this.node2 = n2;

    this.dataIndex = dataIndex == null ? -1 : dataIndex;
}
93739
function showEmbedding(data) {
  const margin = {top: 20, right: 15, bottom: 60, left: 60};
  const width = 800 - margin.left - margin.right;
  const height = 800 - margin.top - margin.bottom;

  const x = d3.scaleLinear().domain([0, 1]).range([0, width]);
  const y = d3.scaleLinear().domain([0, 1]).range([height, 0]);

  const chart = d3.select('body')
                    .append('svg')
                    .attr('width', width + margin.right + margin.left)
                    .attr('height', height + margin.top + margin.bottom)
                    .attr('class', 'chart');

  const main =
      chart.append('g')
          .attr(
              'transform', 'translate(' + margin.left + ',' + margin.top + ')')
          .attr('width', width)
          .attr('height', height)
          .attr('class', 'main');

  const xAxis = d3.axisBottom(x);
  main.append('g')
      .attr('transform', 'translate(0,' + height + ')')
      .attr('class', 'main axis date')
      .call(xAxis);

  const yAxis = d3.axisLeft(y);
  main.append('g')
      .attr('transform', 'translate(0,0)')
      .attr('class', 'main axis date')
      .call(yAxis);

  const dots = main.append('g');

  dots.selectAll('scatter-dots')
      .data(data)
      .enter()
      .append('svg:circle')
      .attr('cx', (d) => x(d[0]))
      .attr('cy', (d) => y(d[1]))
      .attr('stroke-width', 0.25)
      .attr('stroke', '#1f77b4')
      .attr('fill', 'none')
      .attr('r', 5);
}
888735
def get_best_ip_by_real_data_fetch(_type='stock'):
    
    from QUANTAXIS.QAUtil.QADate import QA_util_today_str
    import time
    
    #找到前两天的有效交易日期
    pre_trade_date=QA_util_get_real_date(QA_util_today_str())
    pre_trade_date=QA_util_get_real_date(pre_trade_date)
    
    # 某个函数获取的耗时测试
    def get_stock_data_by_ip(ips):
        start=time.time()
        try:
            QA_fetch_get_stock_transaction('000001',pre_trade_date,pre_trade_date,2,ips['ip'],ips['port'])
            end=time.time()
            return end-start
        except:
            return 9999

    def get_future_data_by_ip(ips):
        start=time.time()
        try:
            QA_fetch_get_future_transaction('RBL8',pre_trade_date,pre_trade_date,2,ips['ip'],ips['port'])
            end=time.time()
            return end-start
        except:
            return 9999

    func,ip_list=0,0
    if _type=='stock':
        func,ip_list=get_stock_data_by_ip,stock_ip_list
    else:
        func,ip_list=get_future_data_by_ip,future_ip_list  
    from pathos.multiprocessing import Pool
    def multiMap(func,sequence):
        res=[]
        pool=Pool(4)
        for i in sequence:
            res.append(pool.apply_async(func,(i,)))
        pool.close()
        pool.join()
        return list(map(lambda x:x.get(),res))
   
    res=multiMap(func,ip_list)
    index=res.index(min(res))
    return ip_list[index]
678858
def get_all(symbol):
    
    ids = \
        'ydb2r1b3qpoc1d1cd2c6t1k2p2c8m5c3m6gm7hm8k1m3lm4l1t8w1g1w4g3p' \
        '1g4mg5m2g6kvjj1j5j3k4f6j6nk5n4ws1xj2va5b6k3t7a2t615l2el3e7v1' \
        'e8v7e9s6b4j4p5p6rr2r5r6r7s7'
    values = _request(symbol, ids).split(',')
    return dict(
        dividend_yield=values[0],
        dividend_per_share=values[1],
        ask_realtime=values[2],
        dividend_pay_date=values[3],
        bid_realtime=values[4],
        ex_dividend_date=values[5],
        previous_close=values[6],
        today_open=values[7],
        change=values[8],
        last_trade_date=values[9],
        change_percent_change=values[10],
        trade_date=values[11],
        change_realtime=values[12],
        last_trade_time=values[13],
        change_percent_realtime=values[14],
        change_percent=values[15],
        after_hours_change_realtime=values[16],
        change_200_sma=values[17],
        todays_low=values[18],
        change_50_sma=values[19],
        todays_high=values[20],
        percent_change_50_sma=values[21],
        last_trade_realtime_time=values[22],
        fifty_sma=values[23],
        last_trade_time_plus=values[24],
        twohundred_sma=values[25],
        last_trade_price=values[26],
        one_year_target=values[27],
        todays_value_change=values[28],
        holdings_gain_percent=values[29],
        todays_value_change_realtime=values[30],
        annualized_gain=values[31],
        price_paid=values[32],
        holdings_gain=values[33],
        todays_range=values[34],
        holdings_gain_percent_realtime=values[35],
        todays_range_realtime=values[36],
        holdings_gain_realtime=values[37],
        fiftytwo_week_high=values[38],
        more_info=values[39],
        fiftytwo_week_low=values[40],
        market_cap=values[41],
        change_from_52_week_low=values[42],
        market_cap_realtime=values[43],
        change_from_52_week_high=values[44],
        float_shares=values[45],
        percent_change_from_52_week_low=values[46],
        company_name=values[47],
        percent_change_from_52_week_high=values[48],
        notes=values[49],
        fiftytwo_week_range=values[50],
        shares_owned=values[51],
        stock_exchange=values[52],
        shares_outstanding=values[53],
        volume=values[54],
        ask_size=values[55],
        bid_size=values[56],
        last_trade_size=values[57],
        ticker_trend=values[58],
        average_daily_volume=values[59],
        trade_links=values[60],
        order_book_realtime=values[61],
        high_limit=values[62],
        eps=values[63],
        low_limit=values[64],
        eps_estimate_current_year=values[65],
        holdings_value=values[66],
        eps_estimate_next_year=values[67],
        holdings_value_realtime=values[68],
        eps_estimate_next_quarter=values[69],
        revenue=values[70],
        book_value=values[71],
        ebitda=values[72],
        price_sales=values[73],
        price_book=values[74],
        pe=values[75],
        pe_realtime=values[76],
        peg=values[77],
        price_eps_estimate_current_year=values[78],
        price_eps_estimate_next_year=values[79],
        short_ratio=values[80],
    )
1367268
def QA_data_stock_to_fq(__data, type_='01'):

    def __QA_fetch_stock_xdxr(
            code,
            format_='pd',
            collections=DATABASE.stock_xdxr
    ):
        '获取股票除权信息/数据库'
        try:
            data = pd.DataFrame(
                [item for item in collections.find({'code': code})]
            ).drop(['_id'],
                   axis=1)
            data['date'] = pd.to_datetime(data['date'])
            return data.set_index(['date', 'code'], drop=False)
        except:
            return pd.DataFrame(
                data=[],
                columns=[
                    'category',
                    'category_meaning',
                    'code',
                    'date',
                    'fenhong',
                    'fenshu',
                    'liquidity_after',
                    'liquidity_before',
                    'name',
                    'peigu',
                    'peigujia',
                    'shares_after',
                    'shares_before',
                    'songzhuangu',
                    'suogu',
                    'xingquanjia'
                ]
            )

    ''

    code = __data.index.remove_unused_levels().levels[1][0] if isinstance(
        __data.index,
        pd.core.indexes.multi.MultiIndex
    ) else __data['code'][0]

    return _QA_data_stock_to_fq(
        bfq_data=__data,
        xdxr_data=__QA_fetch_stock_xdxr(code),
        fqtype=type_
    )
458986
function () {
		var chart = this.chart,
			options = this.options,
			offsetLeft = options.offsetLeft || 0,
			offsetRight = options.offsetRight || 0,
			horiz = this.horiz,
			width,
			height,
			top,
			left;

		// Expose basic values to use in Series object and navigator
		this.left = left = pick(options.left, chart.plotLeft + offsetLeft);
		this.top = top = pick(options.top, chart.plotTop);
		this.width = width = pick(options.width, chart.plotWidth - offsetLeft + offsetRight);
		this.height = height = pick(options.height, chart.plotHeight);
		this.bottom = chart.chartHeight - height - top;
		this.right = chart.chartWidth - width - left;

		// Direction agnostic properties
		this.len = mathMax(horiz ? width : height, 0); // mathMax fixes #905
		this.pos = horiz ? left : top; // distance from SVG origin
	}
26367
def _get_chart_info(df, vtype, cat, prep, callers):
    
    maxval_raw = max(list(df["value.floor"]))
    curdf = df[(df["variant.type"] == vtype) & (df["category"] == cat)
               & (df["bamprep"] == prep)]
    vals = []
    labels = []
    for c in callers:
        row = curdf[df["caller"] == c]
        if len(row) > 0:
            vals.append(list(row["value.floor"])[0])
            labels.append(list(row["value"])[0])
        else:
            vals.append(1)
            labels.append("")
    return vals, labels, maxval_raw
442184
def run(self):
        
        # 如果出现了日期的改变 才会进行结算的事件
        _date = None

        while QA_util_if_tradetime(self.now):
            for data in self.ingest_data:  # 对于在ingest_data中的数据
                # <class 'QUANTAXIS.QAData.QADataStruct.QA_DataStruct_Stock_day'>
                date = data.date[0]
                if self.market_type is MARKET_TYPE.STOCK_CN:  # 如果是股票市场
                    if _date != date:  # 如果新的date
                        # 前一天的交易日已经过去
                        # 往 broker 和 account 发送 settle 事件
                        try:
                            self.market.trade_engine.join()
                            # time.sleep(2)
                            self.market._settle(self.broker_name)

                        except Exception as e:
                            raise e
                # 基金 指数 期货
                elif self.market_type in [MARKET_TYPE.FUND_CN, MARKET_TYPE.INDEX_CN, MARKET_TYPE.FUTURE_CN]:
                    self.market._settle(self.broker_name)
                # print(data)
                self.broker.run(
                    QA_Event(event_type=ENGINE_EVENT.UPCOMING_DATA, market_data=data))
                # 生成 UPCOMING_DATA 事件放到 队列中去执行

                self.market.upcoming_data(self.broker_name, data)

                self.market.trade_engine.join()

                _date = date
752734
def allStockQoutation(self):
        '''
        
        '''
        logger = Logs().getNewLogger('allStockQoutation', QoutationAsynPush.dir)
        markets= [Market.HK,Market.US,Market.SH,Market.SZ] #,Market.HK_FUTURE,Market.US_OPTION
        stockTypes = [SecurityType.STOCK,SecurityType.WARRANT,SecurityType.IDX,SecurityType.BOND,SecurityType.ETF]

        for stockType in stockTypes:
            for market in markets:
                ret_code_stock_basicinfo ,ret_data_stock_basicinfo = self.quote_ctx.get_stock_basicinfo(market,stockType)
                codes = ret_data_stock_basicinfo['code'].tolist()
                codes_len = len(codes)
                code_sub = 0
                code_sub_succ = 0
                for code in codes:
                    ret_code = self.aStockQoutation(code)
                    code_sub += 1
                    if ret_code is RET_OK:
                        code_sub_succ += 1
                        logger.info('市场 = %s，股票类型 = %s, 股票总数 = %d, 已发起订阅 = %d，订阅成功 = %d' % (market, stockType, codes_len, code_sub,code_sub_succ))  # 记录
                logger.info('end-------->市场 = %s，股票类型 = %s, 股票总数 = %d, 已发起订阅 = %d，订阅成功 = %d' % ( market, stockType, codes_len, code_sub,code_sub_succ))  # 记录

        time.sleep(5)
        self.quote_ctx.stop()
        self.quote_ctx.close()
693218
function() {
      var n = JSLitmus._tests.length, markers = [], data = [];
      var d, min = 0, max = -1e10;
      var normalize = jsl.$('test_normalize').checked;

      // Gather test data
      for (var i=0; i < JSLitmus._tests.length; i++) {
        var test = JSLitmus._tests[i];
        if (test.count) {
          var hz = test.getHz(normalize);
          var v = hz != Infinity ? hz : 0;
          data.push(v);
          markers.push('t' + jsl.escape(test.name + '(' + jsl.toLabel(hz)+ ')') + ',000000,0,' +
            markers.length + ',10');
          max = Math.max(v, max);
        }
      }
      if (markers.length <= 0) return null;

      // Build chart title
      var title = document.getElementsByTagName('title');
      title = (title && title.length) ? title[0].innerHTML : null;
      var chart_title = [];
      if (title) chart_title.push(title);
      chart_title.push('Ops/sec (' + platform + ')');

      // Build labels
      var labels = [jsl.toLabel(min), jsl.toLabel(max)];

      var w = 250, bw = 15;
      var bs = 5;
      var h = markers.length*(bw + bs) + 30 + chart_title.length*20;

      var params = {
        chtt: escape(chart_title.join('|')),
        chts: '000000,10',
        cht: 'bhg',                     // chart type
        chd: 't:' + data.join(','),     // data set
        chds: min + ',' + max,          // max/min of data
        chxt: 'x',                      // label axes
        chxl: '0:|' + labels.join('|'), // labels
        chsp: '0,1',
        chm: markers.join('|'),         // test names
        chbh: [bw, 0, bs].join(','),    // bar widths
        // chf: 'bg,lg,0,eeeeee,0,eeeeee,.5,ffffff,1', // gradient
        chs: w + 'x' + h
      };
      return 'http://chart.apis.google.com/chart?' + jsl.join(params, '=', '&');
    }
134026
public String toECharts() {

        TriFunction<Integer, Integer, List<Stopwatch>, String> formatLevel = (
                totalDepth, depth, items) -> {
            float factor = 100.0f / (totalDepth + 1);
            float showFactor = 1 + (totalDepth - depth) / (float) depth;

            float radiusFrom = depth * factor;
            float radiusTo = depth * factor + factor;
            if (depth == 1) {
                radiusFrom = 0;
            }

            StringBuilder sb = new StringBuilder(8 + items.size() * 128);
            sb.append('{');
            sb.append("name: 'Total Cost',");
            sb.append("type: 'pie',");
            sb.append(String.format("radius: ['%s%%', '%s%%'],",
                                    radiusFrom, radiusTo));
            sb.append(String.format(
                    "label: {normal: {position: 'inner', formatter:" +
                    "function(params) {" +
                    "  if (params.percent > %s) return params.data.name;" +
                    "  else return '';" +
                    "}}},", showFactor));
            sb.append("data: [");

            items.sort((i, j) -> i.id().compareTo(j.id()));
            for (Stopwatch w : items) {
                sb.append('{');

                sb.append("value:");
                sb.append(w.totalCost() / 1000000.0);
                sb.append(',');

                sb.append("min:");
                sb.append(w.minCost());
                sb.append(',');

                sb.append("max:");
                sb.append(w.maxCost());
                sb.append(',');

                sb.append("id:'");
                sb.append(w.id());
                sb.append("',");

                sb.append("name:'");
                sb.append(w.name());
                sb.append("',");

                sb.append("times:");
                sb.append(w.times());

                sb.append('}');
                sb.append(',');
            }
            if (!items.isEmpty()) {
                sb.deleteCharAt(sb.length() - 1);
            }
            sb.append("]}");
            return sb.toString();
        };

        BiConsumer<List<Stopwatch>, List<Stopwatch>> fillOther =
            (itemsOfI, parents) -> {
            for (Stopwatch parent : parents) {
                Stream<Stopwatch> children = itemsOfI.stream().filter(c -> {
                    return c.parent().equals(parent.id());
                });
                long sum = children.mapToLong(c -> c.totalCost()).sum();
                if (sum < parent.totalCost()) {
                    Stopwatch other = new Stopwatch("~", parent.id());
                    other.totalCost(parent.totalCost() - sum);
                    itemsOfI.add(other);
                }
            }
        };

        Map<String, Stopwatch> items = this.stopwatches;
        Map<Integer, List<Stopwatch>> levelItems = new HashMap<>();
        int maxDepth = 1;
        for (Map.Entry<String, Stopwatch> e : items.entrySet()) {
            int depth = e.getKey().split("/").length;
            levelItems.putIfAbsent(depth, new LinkedList<>());
            levelItems.get(depth).add(e.getValue().copy());
            if (depth > maxDepth) {
                maxDepth = depth;
            }
        }

        StringBuilder sb = new StringBuilder(8 + items.size() * 128);
        sb.append("{");
        sb.append("tooltip: {trigger: 'item', " +
            "formatter: function(params) {" +
            "    return params.data.name + ' ' + params.percent + '% <br/>'" +
            "        + 'cost: ' + params.data.value + ' (ms) <br/>'" +
            "        + 'min: ' + params.data.min + ' (ns) <br/>'" +
            "        + 'max: ' + params.data.max + ' (ns) <br/>'" +
            "        + 'times: ' + params.data.times + '<br/>'" +
            "       + params.data.id + '<br/>';" +
            "}");
        sb.append("},");
        sb.append("series: [");
        for (int i = 1; levelItems.containsKey(i); i++) {
            List<Stopwatch> itemsOfI = levelItems.get(i);
            if (i > 1) {
                fillOther.accept(itemsOfI, levelItems.get(i - 1));
            }
            sb.append(formatLevel.apply(maxDepth, i, itemsOfI));
            sb.append(',');
        }
        if (!items.isEmpty()) {
            sb.deleteCharAt(sb.length() - 1);
        }
        sb.append("]}");

        return sb.toString();
    }
1128379
def C_stock(self):
        
        return self._C_sys * (self._Q_sys / self._Q_stock).to(u.dimensionless)
695125
function () {

		var options = chart.options.legend;

		if (!options.enabled) {
			return;
		}

		var horizontal = options.layout === 'horizontal',
			symbolWidth = options.symbolWidth,
			symbolPadding = options.symbolPadding,
			allItems,
			style = options.style,
			itemStyle = options.itemStyle,
			itemHoverStyle = options.itemHoverStyle,
			itemHiddenStyle = options.itemHiddenStyle,
			padding = pInt(style.padding),
			y = 18,
			initialItemX = 4 + padding + symbolWidth + symbolPadding,
			itemX,
			itemY,
			lastItemY,
			itemHeight = 0,
			box,
			legendBorderWidth = options.borderWidth,
			legendBackgroundColor = options.backgroundColor,
			legendGroup,
			offsetWidth,
			widthOption = options.width,
			series = chart.series,
			reversedLegend = options.reversed;

		// PATCH by Simon Fishel
        //
        // read in hooks from the options object
        //
        // + var hooks = options.hooks || {};
        
        var hooks = options.hooks || {};

		/**
		 * Set the colors for the legend item
		 * @param {Object} item A Series or Point instance
		 * @param {Object} visible Dimmed or colored
		 */
		function colorizeItem(item, visible) {
			var legendItem = item.legendItem,
				legendLine = item.legendLine,
				legendSymbol = item.legendSymbol,
				hiddenColor = itemHiddenStyle.color,
				textColor = visible ? options.itemStyle.color : hiddenColor,
				lineColor = visible ? item.color : hiddenColor,
				symbolAttr = visible ? item.pointAttr[NORMAL_STATE] : {
					stroke: hiddenColor,
					fill: hiddenColor
				};

			if (legendItem) {
				legendItem.css({ fill: textColor });
			}
			if (legendLine) {
				legendLine.attr({ stroke: lineColor });
			}
			if (legendSymbol) {
				legendSymbol.attr(symbolAttr);
			}

		}

		/**
		 * Position the legend item
		 * @param {Object} item A Series or Point instance
		 * @param {Object} visible Dimmed or colored
		 */
		function positionItem(item, itemX, itemY) {
			var legendItem = item.legendItem,
				legendLine = item.legendLine,
				legendSymbol = item.legendSymbol,
				checkbox = item.checkbox;
			if (legendItem) {
				legendItem.attr({
					x: itemX,
					y: itemY
				});
			}
			if (legendLine) {
				legendLine.translate(itemX, itemY - 4);
			}
			if (legendSymbol) {
				legendSymbol.attr({
					x: itemX + legendSymbol.xOff,
					y: itemY + legendSymbol.yOff
				});
			}
			if (checkbox) {
				checkbox.x = itemX;
				checkbox.y = itemY;
			}
		}

		/**
		 * Destroy a single legend item
		 * @param {Object} item The series or point
		 */
		function destroyItem(item) {
			var checkbox = item.checkbox;

			// pull out from the array
			//erase(allItems, item);

			// destroy SVG elements
			each(['legendItem', 'legendLine', 'legendSymbol'], function (key) {
				if (item[key]) {
					item[key].destroy();
				}
			});

			if (checkbox) {
				discardElement(item.checkbox);
			}


		}

		/**
		 * Destroys the legend.
		 */
		function destroy() {
			if (box) {
				box = box.destroy();
			}

			if (legendGroup) {
				legendGroup = legendGroup.destroy();
			}
		}

		/**
		 * Position the checkboxes after the width is determined
		 */
		function positionCheckboxes() {
			each(allItems, function (item) {
				var checkbox = item.checkbox,
					alignAttr = legendGroup.alignAttr;
				if (checkbox) {
					css(checkbox, {
						left: (alignAttr.translateX + item.legendItemWidth + checkbox.x - 40) + PX,
						top: (alignAttr.translateY + checkbox.y - 11) + PX
					});
				}
			});
		}

		/**
		 * Render a single specific legend item
		 * @param {Object} item A series or point
		 */
		function renderItem(item) {
			var bBox,
				itemWidth,
				legendSymbol,
				symbolX,
				symbolY,
				simpleSymbol,
				li = item.legendItem,
				series = item.series || item,
				itemOptions = series.options,
				strokeWidth = (itemOptions && itemOptions.borderWidth) || 0;

			if (!li) { // generate it once, later move it

				// let these series types use a simple symbol
				simpleSymbol = /^(bar|pie|area|column)$/.test(series.type);

				// generate the list item text
				item.legendItem = li = renderer.text(
						options.labelFormatter.call(item),
						0,
						0
					)
					.css(item.visible ? itemStyle : itemHiddenStyle)
					.on('mouseover', function () {
						item.setState(HOVER_STATE);
						li.css(itemHoverStyle);
					})
					.on('mouseout', function () {
						li.css(item.visible ? itemStyle : itemHiddenStyle);
						item.setState();
					})
					
					// PATCH by Simon Fishel
					// 
					// see below
					// 
					// - .on('click', function () {
					// + .on('click', function (event) {
					
					.on('click', function (event) {
						var strLegendItemClick = 'legendItemClick',
							fnLegendItemClick = function () {
								item.setVisible();
							};
						
						// PATCH by Simon Fishel
						//
						// passing any control/command key modifiers to the event handler
						//
						// + var eventArgs = {
                        // +     ctrlKey: event.ctrlKey,
                        // +     metaKey: event.metaKey
                        // + };
						//
						//   // click the name or symbol
	                    //   if (item.firePointEvent) { // point
						// -     item.firePointEvent(strLegendItemClick, null, fnLegendItemClick);
	                    // +     item.firePointEvent(strLegendItemClick, eventArgs, fnLegendItemClick);
	                    //   } else {
						// -     fireEvent(item, strLegendItemClick, null, fnLegendItemClick);
	                    // +     fireEvent(item, strLegendItemClick, eventArgs, fnLegendItemClick);
	                    //   }
							
						var eventArgs = {
						    ctrlKey: event.ctrlKey,
						    metaKey: event.metaKey
						};

						// click the name or symbol
						if (item.firePointEvent) { // point
							item.firePointEvent(strLegendItemClick, eventArgs, fnLegendItemClick);
						} else {
							fireEvent(item, strLegendItemClick, eventArgs, fnLegendItemClick);
						}
					})
					.attr({ zIndex: 2 })
					.add(legendGroup);

				// draw the line
				if (!simpleSymbol && itemOptions && itemOptions.lineWidth) {
					var attrs = {
							'stroke-width': itemOptions.lineWidth,
							zIndex: 2
						};
					if (itemOptions.dashStyle) {
						attrs.dashstyle = itemOptions.dashStyle;
					}
					item.legendLine = renderer.path([
						M,
						-symbolWidth - symbolPadding,
						0,
						L,
						-symbolPadding,
						0
					])
					.attr(attrs)
					.add(legendGroup);
				}

				// draw a simple symbol
				if (simpleSymbol) { // bar|pie|area|column

					legendSymbol = renderer.rect(
						(symbolX = -symbolWidth - symbolPadding),
						(symbolY = -11),
						symbolWidth,
						12,
						2
					).attr({
						//'stroke-width': 0,
						zIndex: 3
					}).add(legendGroup);

				// draw the marker
				} else if (itemOptions && itemOptions.marker && itemOptions.marker.enabled) {
					legendSymbol = renderer.symbol(
						item.symbol,
						(symbolX = -symbolWidth / 2 - symbolPadding),
						(symbolY = -4),
						itemOptions.marker.radius
					)
					//.attr(item.pointAttr[NORMAL_STATE])
					.attr({ zIndex: 3 })
					.add(legendGroup);

				}
				if (legendSymbol) {
					legendSymbol.xOff = symbolX + (strokeWidth % 2 / 2);
					legendSymbol.yOff = symbolY + (strokeWidth % 2 / 2);
				}

				item.legendSymbol = legendSymbol;

				// colorize the items
				colorizeItem(item, item.visible);


				// add the HTML checkbox on top
				if (itemOptions && itemOptions.showCheckbox) {
					item.checkbox = createElement('input', {
						type: 'checkbox',
						checked: item.selected,
						defaultChecked: item.selected // required by IE7
					}, options.itemCheckboxStyle, container);

					addEvent(item.checkbox, 'click', function (event) {
						var target = event.target;
						fireEvent(item, 'checkboxClick', {
								checked: target.checked
							},
							function () {
								item.select();
							}
						);
					});
				}
			}


			// calculate the positions for the next line
			bBox = li.getBBox();

			itemWidth = item.legendItemWidth =
				options.itemWidth || symbolWidth + symbolPadding + bBox.width + padding;
			itemHeight = bBox.height;

			// if the item exceeds the width, start a new line
			if (horizontal && itemX - initialItemX + itemWidth >
					(widthOption || (chartWidth - 2 * padding - initialItemX))) {
				itemX = initialItemX;
				itemY += itemHeight;
			}
			lastItemY = itemY;

			// position the newly generated or reordered items
			positionItem(item, itemX, itemY);

			// advance
			if (horizontal) {
				itemX += itemWidth;
			} else {
				itemY += itemHeight;
			}

			// the width of the widest item
			offsetWidth = widthOption || mathMax(
				horizontal ? itemX - initialItemX : itemWidth,
				offsetWidth
			);



			// add it all to an array to use below
			//allItems.push(item);
		}

		/**
		 * Render the legend. This method can be called both before and after
		 * chart.render. If called after, it will only rearrange items instead
		 * of creating new ones.
		 */
		function renderLegend() {
			itemX = initialItemX;
			itemY = y;
			offsetWidth = 0;
			lastItemY = 0;

			if (!legendGroup) {
				legendGroup = renderer.g('legend')
					.attr({ zIndex: 7 })
					.add();
			}


			// add each series or point
			allItems = [];
			each(series, function (serie) {
				var seriesOptions = serie.options;

				if (!seriesOptions.showInLegend) {
					return;
				}

				// use points or series for the legend item depending on legendType
				allItems = allItems.concat(seriesOptions.legendType === 'point' ?
					serie.data :
					serie
				);

			});

			// sort by legendIndex
			stableSort(allItems, function (a, b) {
				return (a.options.legendIndex || 0) - (b.options.legendIndex || 0);
			});

			// reversed legend
			if (reversedLegend) {
				allItems.reverse();
			}

			// render the items
			
			// PATCH by Simon Fishel
            //
            // call label render hook before rendering the legend items
            //
            // + if(hooks.labelRenderHook) {
            // +    hooks.labelRenderHook(allItems, options, itemStyle, spacingBox, renderer);
            // + }
            
            if(hooks.labelRenderHook) {
                hooks.labelRenderHook(allItems, options, itemStyle, spacingBox, renderer);
            }
			
			each(allItems, renderItem);



			// Draw the border
			legendWidth = widthOption || offsetWidth;
			legendHeight = lastItemY - y + itemHeight;

			if (legendBorderWidth || legendBackgroundColor) {
				legendWidth += 2 * padding;
				legendHeight += 2 * padding;

				if (!box) {
					box = renderer.rect(
						0,
						0,
						legendWidth,
						legendHeight,
						options.borderRadius,
						legendBorderWidth || 0
					).attr({
						stroke: options.borderColor,
						'stroke-width': legendBorderWidth || 0,
						fill: legendBackgroundColor || NONE
					})
					.add(legendGroup)
					.shadow(options.shadow);
					box.isNew = true;

				} else if (legendWidth > 0 && legendHeight > 0) {
					box[box.isNew ? 'attr' : 'animate'](
						box.crisp(null, null, null, legendWidth, legendHeight)
					);
					box.isNew = false;
				}

				// hide the border if no items
				box[allItems.length ? 'show' : 'hide']();
			}

			// 1.x compatibility: positioning based on style
			var props = ['left', 'right', 'top', 'bottom'],
				prop,
				i = 4;
			while (i--) {
				prop = props[i];
				if (style[prop] && style[prop] !== 'auto') {
					options[i < 2 ? 'align' : 'verticalAlign'] = prop;
					options[i < 2 ? 'x' : 'y'] = pInt(style[prop]) * (i % 2 ? -1 : 1);
				}
			}
			
			// PATCH by Simon Fishel
            // 
            // call placement hook before aligning the legend element
            //
            // + if(hooks.placementHook) {
            // +    hooks.placementHook(options, legendWidth, legendHeight, spacingBox);
            // + }
            
            if(hooks.placementHook) {
                hooks.placementHook(options, legendWidth, legendHeight, spacingBox);
            }

			if (allItems.length) {
				legendGroup.align(extend(options, {
					width: legendWidth,
					height: legendHeight
				}), true, spacingBox);
			}

			if (!isResizing) {
				positionCheckboxes();
			}
		}


		// run legend
		renderLegend();

		// move checkboxes
		addEvent(chart, 'endResize', positionCheckboxes);

		// expose
		return {
			colorizeItem: colorizeItem,
			destroyItem: destroyItem,
			renderLegend: renderLegend,
			destroy: destroy
		};
	}
201368
function (d, chart, series) {
            var returnHeight = 0;
            if (series.y._hasTimeField()) {
                returnHeight = series.y.floatingBarWidth;
            } else if (series.y.measure !== null && series.y.measure !== undefined) {
                returnHeight = Math.abs(series.y._scale(d.y) - series.y._scale((d.y <= 0 ? d.y + d.height : d.y - d.height)));
            } else {
                returnHeight = d.height * ((chart._heightPixels() / series.y._max) - (dimple._helpers.yGap(chart, series) * 2)) - (dimple._helpers.yClusterGap(d, chart, series) * 2);
            }
            return returnHeight;
        }
1189341
def loop_get_mkt_snapshot(api_svr_ip, api_svr_port, market):
    
    # 创建行情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()
123260
def handle_data(self):
        
        # 读取历史数据，使用sma方式计算均线准确度和数据长度无关，但是在使用ema方式计算均线时建议将历史数据窗口适当放大，结果会更加准确
        today = datetime.datetime.today()
        pre_day = (today - datetime.timedelta(days=self.observation)
                   ).strftime('%Y-%m-%d')
        end_dt = today.strftime('%Y-%m-%d')
        ret_code, prices = self.quote_ctx.get_history_kline(self.stock, start=pre_day, end=end_dt, ktype=ft.KLType.K_DAY)
        if ret_code != ft.RET_OK:
            print("get_history_kline fail: {}".format(prices))
            return

        # 用talib计算MACD取值，得到三个时间序列数组，分别为 macd, signal 和 hist
        # macd 是长短均线的差值，signal 是 macd 的均线
        # 使用 macd 策略有几种不同的方法，我们这里采用 macd 线突破 signal 线的判断方法
        macd, signal, hist = talib.MACD(prices['close'].values,
                                        self.short_period, self.long_period,
                                        self.smooth_period)

        # 如果macd从上往下跌破macd_signal
        if macd[-1] < signal[-1] and macd[-2] > signal[-2]:
            # 计算现在portfolio中股票的仓位
            ret_code, data = self.trade_ctx.position_list_query(
                trd_env=self.trade_env)

            if ret_code != ft.RET_OK:
                raise Exception('账户信息获取失败: {}'.format(data))
            pos_info = data.set_index('code')

            cur_pos = int(pos_info['qty'][self.stock])
            # 进行清仓
            if cur_pos > 0:
                ret_code, data = self.quote_ctx.get_market_snapshot(
                    [self.stock])
                if ret_code != 0:
                    raise Exception('市场快照数据获取异常 {}'.format(data))
                cur_price = data['last_price'][0]
                ret_code, ret_data = self.trade_ctx.place_order(
                    price=cur_price,
                    qty=cur_pos,
                    code=self.stock,
                    trd_side=ft.TrdSide.SELL,
                    order_type=ft.OrderType.NORMAL,
                    trd_env=self.trade_env)
                if ret_code == ft.RET_OK:
                    print('stop_loss MAKE SELL ORDER\n\tcode = {} price = {} quantity = {}'
                          .format(self.stock, cur_price, cur_pos))
                else:
                    print('stop_loss: MAKE SELL ORDER FAILURE: {}'.format(ret_data))

        # 如果短均线从下往上突破长均线，为入场信号
        if macd[-1] > signal[-1] and macd[-2] < signal[-2]:
            # 满仓入股
            ret_code, acc_info = self.trade_ctx.accinfo_query(
                trd_env=self.trade_env)
            if ret_code != 0:
                raise Exception('账户信息获取失败! 请重试: {}'.format(acc_info))

            ret_code, snapshot = self.quote_ctx.get_market_snapshot(
                [self.stock])
            if ret_code != 0:
                raise Exception('市场快照数据获取异常 {}'.format(snapshot))
            lot_size = snapshot['lot_size'][0]
            cur_price = snapshot['last_price'][0]
            cash = acc_info['Power'][0]  # 购买力
            qty = int(math.floor(cash / cur_price))
            qty = qty // lot_size * lot_size

            ret_code, ret_data = self.trade_ctx.place_order(
                price=cur_price,
                qty=qty,
                code=self.stock,
                trd_side=ft.TrdSide.BUY,
                order_type=ft.OrderType.NORMAL,
                trd_env=self.trade_env)
            if not ret_code:
                print(
                    'stop_loss MAKE BUY ORDER\n\tcode = {} price = {} quantity = {}'
                    .format(self.stock, cur_price, qty))
            else:
                print('stop_loss: MAKE BUY ORDER FAILURE: {}'.format(ret_data))