市場寬度實時定時版
from jqdata import * import datetime as dt import numpy as np import pandas as pd import seaborn as sns import matplotlib.pyplot as plt import json, textwrap # 獲取股票和價格數據 stocks = get_index_stocks("000985.XSHG") now = dt.datetime.now().strftime('%Y-%m-%d %H:%M:%S') yesterday = (dt.datetime.now() - dt.timedelta(days=1)).strftime("%Y-%m-%d") count = 90 #1年的交易日 price_hist = get_price(stocks,end_date=yesterday,frequency="1d",fields=["close"],count=count + 19,panel=False) # 獲取行業信息 def getStockIndustry(stocks): industry = get_industry(stocks) dict = { stock: info["sw_l1"]["industry_name"] for stock, info in industry.items() if "sw_l1" in info } industry_2_stock = {} for stock, info in industry.items(): if "sw_l1" in info: industry_name = info["sw_l1"]["industry_name"] ls = industry_2_stock.get(industry_name, []) ls.append(stock) industry_2_stock[industry_name] = ls return pd.Series(dict), industry_2_stock def update_price(): cur_price = get_price(stocks,end_date=now,frequency="1m",fields=["close"],count=1,panel=False) cur_price['time'] = pd.to_datetime(cur_price['time']).dt.floor('d') new_price = pd.concat([price_hist, cur_price], ignore_index=True) new_price= new_price.sort_values(['code', 'time']).reset_index(drop=True) return new_price def update_df(): # 處理數據 h = update_price() h["date"] = pd.DatetimeIndex(h.time).date df_close = h.pivot(index="code", columns="date", values="close").dropna(axis=0) df_ma20 = df_close.rolling(window=20, axis=1).mean().iloc[:, -count:] df_bias = df_close.iloc[:, -count:] > df_ma20 df_bias["industry_name"], industry_2_stock = getStockIndustry(stocks) df_ratio = ( (df_bias.groupby("industry_name").sum() * 100.0) / df_bias.groupby("industry_name").count() ).round() df_ratio.loc['合計'] = df_ratio.sum().astype("int32") DF = df_ratio.T return DF #====================================================================== def update_html(DF): industry_cols = DF.columns[:-1] df = DF.iloc[:, :-1].copy() # 創建數據框副本,避免修改原始數據 df.insert(len(industry_cols), '市場平均', df[industry_cols].mean(axis=1).round().astype(int)) df.index = pd.to_datetime(df.index) use_cols = [c for c in df.columns if c not in {'合計'}] # 1. 只保留 [x, y, value] 三元組給 ECharts data_js = [ [j, i, int(df.iloc[i, j])] for i in range(len(df)) for j in range(len(df.columns)) ] # print("data_js:", data_js) # 2. 行業名、日期單獨傳兩份數組,前端用索引去取 cols = df.columns.tolist() # print("cols:", cols) dates = [str(d) for d in df.index.date] # print("dates:", dates) cell_w = 40 # 每列寬 80 px cell_h = 40 # 每行高 26 px(足夠看清文字) width = len(use_cols) * cell_w # 留邊給 visualMap height = len(df) * cell_h # 隨行情自動增高 # 寫進單文件 HTML html = textwrap.dedent(f'''\ <!doctype html> <html> <head> <meta charset="utf-8"><title>行業熱力圖(可點擊)</title> <script src="https://cdn.jsdelivr.net/npm/echarts@5/dist/echarts.min.js"></script> <style> #wrapper{{width:100%;max-height:70vh;overflow:auto;border:1px solid #ddd}} #chart{{width:{width}px;height:{height}px;margin:auto}} </style> </head> <body> <div id="chart" style="width:{{width}}px;height:{{height}}px;margin:auto"></div> <script> const raw = {json.dumps(data_js)}; const cols = {json.dumps(cols)}; const dates = {json.dumps(dates)}; const myChart = echarts.init(document.getElementById('chart')); const option = {{ tooltip: {{ position: 'top', formatter: p => {{ const [x, y, val] = p.data; return `${{dates[y]}}<br/>${{cols[x]}}: <b>${{val}}</b>`; }} }}, animation: true, grid: {{left: '10%', right: '5%', bottom: '5%', top: '2%'}}, xAxis: {{ type: 'category', data: cols, position: 'top', axisLabel: {{interval: 0,rotate: 45,fontSize: 11}}, splitArea: {{show: true}} }}, yAxis: {{ type: 'category', data: dates, splitArea: {{show: true}} }}, visualMap: {{ min: 0, max: 100, calculable: true, type: 'continuous', orient: 'horizontal', left: 'center', bottom: '2%', inRange: {{color: [ '#005824','#238b45','#5cb85c','#90ee90','#ffff99', '#ffaa99','#ff7d66','#f54437','#b00000' ]}} }}, series: [{{ name: '熱力圖', type: 'heatmap', data: raw, label: {{show: true, fontSize: 11, color: '#000'}}, itemStyle: {{borderWidth: 1, borderColor: '#fff'}}, emphasis: {{itemStyle: {{shadowBlur: 12, shadowColor: 'rgba(0,0,0,.4'}}}} }}] }}; myChart.setOption(option); // 點擊事件 myChart.on('click', params => {{ const [,,val,ind,dt] = params.data; alert(`${{dt}}\\n${{ind}}: ${{val}}`); }}); </script> </body> </html>''') open('行業寬度-定時刷新版.html','w',encoding='utf-8').write(html) print("可以打開-行業寬度-定時刷新版.html") # 定時刷新 10分鐘一次 while True: DF = update_df() update_html(DF) time.sleep(60 * 10)
本文來自博客園,作者:羊駝之歌,轉載請注明原文鏈接:http://www.rzrgm.cn/shijieli/p/19131049

浙公網安備 33010602011771號