
    fi5*                         d Z ddlmZ ddlZddlZddlZddededej        fd	Ze	d
k    r edd          Z
 ee
           dS dS )u   
Date: 2025/11/4 18:00
Desc: 东方财富网-概念板-行情中心-日K-筹码分布
https://quote.eastmoney.com/concept/sz000001.html
    )datetimeN000001 symboladjustreturnc                 	   d}t          j                    }|                    |           dddd}|                     d          rdnd}d	}| d
|  ddd||         t	          j                                                                        d          dd}t          j	        ||          }|
                                }	t          j        d |	d         d         D                       }
g d|
_        |
j        dd         D ]}t          j        |
|                   |
|<    t          dt!          |
                    |
d<   |
                    d          }g }g }g }g }g }g }g }g }g }t          dt!          |                    D ]s}|                    d||          }|                    ||         d                    |                    |d                    |                    |d                    |                    |d         d         d          d                    |                    |d         d         d          d                    |                    |d         d!         d          d                    |                    |d         d!         d          d                    |                    |d         d         d"                    |                    |d         d!         d"                    ut          j        |||||||||g	          j        }
g d#|
_        t          j        |
d$         d%&          j        j        |
d$<   t          j        |
d'         d%&          |
d'<   t          j        |
d(         d%&          |
d(<   t          j        |
d)         d%&          |
d)<   t          j        |
d*         d%&          |
d*<   t          j        |
d+         d%&          |
d+<   t          j        |
d,         d%&          |
d,<   t          j        |
d-         d%&          |
d-<   t          j        |
d.         d%&          |
d.<   |
j        d/dddf                                         }
|
                    d0d01           |
S )2uR  
    东方财富网-概念板-行情中心-日K-筹码分布
    https://quote.eastmoney.com/concept/sz000001.html
    :param symbol: 股票代码
    :type symbol: str
    :param adjust: choice of {"qfq": "前复权", "hfq": "后复权", "": "不复权"}
    :type adjust: str
    :return: 筹码分布
    :rtype: pandas.DataFrame
    u  
    // @ts-nocheck

    /**
     * 计算分布及相关指标
     * @param {number} index 当前选中的K线的索引
     * @return {{x: Array.<number>, y: Array.<number>}}
     */
    /**
    this.range = 120;
    */
    function CYQCalculator(index, klinedata) {
        var maxprice = 0;
        var minprice = 0;
        var factor = 150;
        var start = this.range ? Math.max(0, index - this.range + 1) : 0;
        /**
         * K图数据[time,open,close,high,low,volume,amount,amplitude,turnoverRate]
         */
        var kdata = klinedata.slice(start, Math.max(1, index + 1));
        if (kdata.length === 0) throw 'invaild index';
        for (var i = 0; i < kdata.length; i++) {
            var elements = kdata[i];
            maxprice = !maxprice ? elements.high : Math.max(maxprice, elements.high);
            minprice = !minprice ? elements.low : Math.min(minprice, elements.low);
        }

        // 精度不小于0.01 产品逻辑
        var accuracy = Math.max(0.01, (maxprice - minprice) / (factor - 1));
        /**
         * 值域
         * @type {Array.<number>}
         */
        var yrange = [];
        for (var i = 0; i < factor; i++) {
            yrange.push((minprice + accuracy * i).toFixed(2) / 1);
        }
        /**
         * 横轴数据
         */
        var xdata = createNumberArray(factor);

        for (var i = 0; i < kdata.length; i++) {
            var eles = kdata[i];

            var open = eles.open,
                close = eles.close,
                high = eles.high,
                low = eles.low,
                avg = (open + close + high + low) / 4,
                turnoverRate = Math.min(1, eles.hsl / 100 || 0);

            var H = Math.floor((high - minprice) / accuracy),
                L = Math.ceil((low - minprice) / accuracy),
                // G点坐标, 一字板时, X为进度因子
                GPoint = [high == low ? factor - 1 : 2 / (high - low), Math.floor((avg - minprice) / accuracy)];
            // 衰减
            for (var n = 0; n < xdata.length; n++) {
                xdata[n] *= (1 - turnoverRate);
            }

            if (high == low) {
                // 一字板时，画矩形面积是三角形的2倍
                xdata[GPoint[1]] += GPoint[0] * turnoverRate / 2;
            } else {
                for (var j = L; j <= H; j++) {
                    var curprice = minprice + accuracy * j;
                    if (curprice <= avg) {
                        // 上半三角叠加分布分布
                        if (Math.abs(avg - low) < 1e-8) {
                            xdata[j] += GPoint[0] * turnoverRate;
                        } else {
                            xdata[j] += (curprice - low) / (avg - low) * GPoint[0] * turnoverRate;
                        }
                    } else {
                        // 下半三角叠加分布分布
                        if (Math.abs(high - avg) < 1e-8) {
                            xdata[j] += GPoint[0] * turnoverRate;
                        } else {
                            xdata[j] += (high - curprice) / (high - avg) * GPoint[0] * turnoverRate;
                        }
                    }
                }
            }

        }


        var currentprice = klinedata[index].close;
        var totalChips = 0;
        for (var i = 0; i < factor; i++) {
            var x = xdata[i].toPrecision(12) / 1;
            //if (x < 0) xdata[i] = 0;
            totalChips += x;
        }
        var result = new CYQData();
        result.x = xdata;
        result.y = yrange;
        result.benefitPart = result.getBenefitPart(currentprice);
        result.avgCost = getCostByChip(totalChips * 0.5).toFixed(2);
        result.percentChips = {
            '90': result.computePercentChips(0.9),
            '70': result.computePercentChips(0.7)
        };
        return result;

        /**
         * 获取指定筹码处的成本
         * @param {number} chip 堆叠筹码
         */
        function getCostByChip(chip) {
            var result = 0,
                sum = 0;
            for (var i = 0; i < factor; i++) {
                var x = xdata[i].toPrecision(12) / 1;
                if (sum + x > chip) {
                    result = minprice + i * accuracy;
                    break;
                }
                sum += x;
            }
            return result;
        }

        /**
         * 筹码分布数据
         */
        function CYQData() {
            /**
             * 筹码堆叠
             * @type {Array.<number>}
             */
            this.x = arguments[0];
            /**
             * 价格分布
             * @type {Array.<number>}
             */
            this.y = arguments[1];
            /**
             * 获利比例
             * @type {number}
             */
            this.benefitPart = arguments[2];
            /**
             * 平均成本
             * @type {number}
             */
            this.avgCost = arguments[3];
            /**
             * 百分比筹码
             * @type {{Object.<string, {{priceRange: number[], concentration: number}}>}}
             */
            this.percentChips = arguments[4];
            /**
             * 计算指定百分比的筹码
             * @param {number} percent 百分比大于0，小于1
             */
            this.computePercentChips = function (percent) {
                if (percent > 1 || percent < 0) throw 'argument "percent" out of range';
                var ps = [(1 - percent) / 2, (1 + percent) / 2];
                var pr = [getCostByChip(totalChips * ps[0]), getCostByChip(totalChips * ps[1])];
                return {
                    priceRange: [pr[0].toFixed(2), pr[1].toFixed(2)],
                    concentration: pr[0] + pr[1] === 0 ? 0 : (pr[1] - pr[0]) / (pr[0] + pr[1])
                };
            };
            /**
             * 获取指定价格的获利比例
             * @param {number} price 价格
             */
            this.getBenefitPart = function (price) {
                var below = 0;
                for (var i = 0; i < factor; i++) {
                    var x = xdata[i].toPrecision(12) / 1;
                    if (price >= minprice + i * accuracy) {
                        below += x;
                    }
                }
                return totalChips == 0 ? 0 : below / totalChips;
            };
        }
    }


    function createNumberArray(count) {
        var array = [];
        for (var i = 0; i < count; i++) {
            array.push(0);
        }
        return array;
    }
    120)qfqhfqr   6   r   z5https://push2his.eastmoney.com/api/qt/stock/kline/get.zf1,f2,f3,f4,f5,f6z+f51,f52,f53,f54,f55,f56,f57,f58,f59,f60,f61101z%Y%m%d210)secidfields1fields2kltfqtendlmt)paramsc                 8    g | ]}|                     d           S ),)split).0items     M/usr/local/lib/python3.11/dist-packages/akshare/stock_feature/stock_cyq_em.py
<listcomp>z stock_cyq_em.<locals>.<listcomp>   s"    TTTDJJsOOTTT    dataklines)dateopenclosehighlowvolumevolume_moneyzfzdfzdehslNindexrecords)orientCYQCalculatorr&   benefitPartavgCostpercentChips70
priceRange90concentration)	   日期   获利比例   平均成本   90成本-低   90成本-高   90集中度   70成本-低   70成本-高   70集中度r<   coerce)errorsr=   r>   r?   r@   rA   rB   rC   rD   iT)inplacedrop)py_mini_racer	MiniRacereval
startswithr   nowr&   strftimerequestsgetjsonpd	DataFramecolumns
to_numericrangelento_dictcallappendTto_datetimedtiloccopyreset_index)r   r   html_strjs_codeadjust_dictmarket_codeurlr   r	data_jsontemp_dfr    r2   	date_listbenefit_partavg_cost
pct_70_lowpct_70_high
pct_90_lowpct_90_high
pct_70_con
pct_90_conimcodes                           r!   stock_cyq_emrt      s   H@ %''GLLcs33K((--4!!1K
AC**&**&@6"|~~""$$--h77 F 	S(((AIlTT	&8I(8STTTUUG  GO # 5 5gdm44QG--GGooYo//GILHJKJKJJ1c'll## 
H 
H_a99F+,,,E-0111i()))%/5lCAFGGG506|DQGHHH%/5lCAFGGG506|DQGHHH%/5oFGGG%/5oFGGGGl
	
   
 
 
GO wx'8JJJMRGH mGN,CHUUUGN mGN,CHUUUGN mGN,CHUUUGN mGN,CHUUUGN]7=+A(SSSGM mGN,CHUUUGN mGN,CHUUUGN]7=+A(SSSGMl3447#((**G4000Nr#   __main__)r   r   )r   r   )__doc__r   pandasrR   rI   rO   strrS   rt   __name__stock_cyq_em_dfprint r#   r!   <module>r}      s                   d d d dbl d d d dN	 z"l(2>>>O	E/ r#   