From f6224f08c9916d71f1251a776ece8044ea36957f Mon Sep 17 00:00:00 2001 From: Porter Date: Sun, 1 Jun 2025 01:13:00 +0800 Subject: [PATCH] Change layout --- __pycache__/ChanBI.cpython-312.pyc | Bin 6715 -> 6709 bytes __pycache__/ChanBSP.cpython-312.pyc | Bin 1359 -> 1368 bytes __pycache__/ChanCTime.cpython-312.pyc | Bin 3396 -> 3405 bytes __pycache__/ChanEnum.cpython-312.pyc | Bin 6292 -> 6301 bytes __pycache__/ChanKLC.cpython-312.pyc | Bin 72824 -> 72791 bytes __pycache__/ChanKLU.cpython-312.pyc | Bin 16082 -> 16071 bytes __pycache__/ChanLun.cpython-312.pyc | Bin 112936 -> 112562 bytes __pycache__/ChanSBI.cpython-312.pyc | Bin 3867 -> 3876 bytes __pycache__/ChanSEG.cpython-312.pyc | Bin 3479 -> 3488 bytes __pycache__/ChanZS.cpython-312.pyc | Bin 3796 -> 3805 bytes web/app.py | 69 ++++-- web/templates/index.html | 306 +++++++++++++++++++++----- 12 files changed, 302 insertions(+), 73 deletions(-) diff --git a/__pycache__/ChanBI.cpython-312.pyc b/__pycache__/ChanBI.cpython-312.pyc index b454148d40b96e45bf67ab8a55b2b8f3f3b519be..9b13e87b356c9d0e25b2e6fe93aeb6a8183abc92 100644 GIT binary patch delta 132 zcmdmOvekt9G%qg~0}x1Q@onU`VV1Sm4=qkDD%Q_ROwQJK$xklLP0cGQ)_2b=@hDB& z9L@ZNRkjhRyn*3{ut`AQbe2int;ya9uakB20`7;+eG|W8E;Kyl`;bWMP(YNFDRck; diff --git a/__pycache__/ChanBSP.cpython-312.pyc b/__pycache__/ChanBSP.cpython-312.pyc index 177daec74704ed80a648f080380c6b15ebd02be3..cc05b4cce47830f5a8acf5fa538a820e3e139dbd 100644 GIT binary patch delta 62 zcmX@lb%TrNG%qg~0}vee$Cj~?=Nyx)gMMgnYEiL%R$_9tzDs^`X>Mv>NwL0rW{F2> R(&l$e`b>1UOpL!K ItFsyc0LNJoiU0rr diff --git a/__pycache__/ChanCTime.cpython-312.pyc b/__pycache__/ChanCTime.cpython-312.pyc index b9efe3f5ed8e57ce8f5400c2c88103387ea80110..c08bfc5fa9dff8e5604de28374d71f213e750d71 100644 GIT binary patch delta 79 zcmX>ibykY!G%qg~0}vee$Cj~?=Q^XTlYVG%YEiL%R$_9tzDs^`X>Mv>NwL0rW{F2> i(&q1sHyOEaG3wu9GBCQusBmlZZDuP@##@ucc=Z4-GaG#X delta 69 zcmX>rbwrBiG%qg~0}v=Iyp+C?=Q^W^rG98}YEiL%R$_9ten3%vR%&v|CZ?N=+`kz0 YZ!sAd-C|VuwfPCN6({4b$@08<01>MfX8-^I diff --git a/__pycache__/ChanEnum.cpython-312.pyc b/__pycache__/ChanEnum.cpython-312.pyc index 0e8de31bdeddbea2654b7c9e6180e118d449cd69..60e4aad0907431f15607de2dcd005cd7af2fc802 100644 GIT binary patch delta 62 zcmbPYIM^5 HaSKKOkZupj diff --git a/__pycache__/ChanKLC.cpython-312.pyc b/__pycache__/ChanKLC.cpython-312.pyc index 9b0f3f530fceba908c9e13216e885d96238bf9be..2436f2e8eed4d250a63f3bfab1c4998fbbbe1d1b 100644 GIT binary patch delta 794 zcmZXSZAcSw9LMj!v()BR?ZK(@ZqAvawJo)Bu9nuEI}z!{2$ZnU6*gX^&&~p$m7h--UL0os8>b>L2o*f=taMG-!C724}5<=g{-uY zrJmPlHX%y=>T+}H)(u#r^KkgYK-k&a73_01oe2*1pE!L!?DU7u6NBA+?}p}$zyLXQ zHM(rH!!PO)6v=n+J$df|I0Rd@MXKlpcuMO)kpe4!PkUescnII&*1~8#<;~#MG+ra& zH8Q>{jk_h>y^QaJHcOKRv3OQd#DIM>Achh+Y$;Ym34hmetsh+B%Ww2-R*e?I+Y?qV zqBDQhB6-G@1|k~fa%Hod%T4LWypzN@!RAV4_mXMv?D5y3xe!IHc$%X@CL|ZRm=GNv ztDUSHuS7{WQtvJ*WZh|9h1Yl98aAGbVFvp!o;>od?nYHZ4o`Pu|@Q--e_>lHd%S6k`5+& z;yqH4<4wL(@bHg?gLxncf4rzwjTS)X%nlUM74b)B>?p{A*Jm5i<@}v+Y4#+Fn5y~x zb9>h8!G(4E>B72Q@oL^v$S5y+30ciSj3z2Kvsq7NecYNK85*_3wy43N($)HeQiDeT jJMtIQ8>wssyg77r=pWpn0k%KzMGX+O;BBnF7&QC_v^^=a delta 790 zcmY+CUr19?7{KrGPVcVsPIGsE+~(#sOB8jc=%zMI=k$t1g$er5-z7Q!5V@k#Ry_`) zm>uI93SL>bi%4C&58mp*hy+EWIqNoGBBUOAC~Wl*_0kzZ(0TZNAN=5a=lj0%PE!1o z6smQK%Er*yFu501otd=D*&XZ~2|5Q(`v;vzM$QlP`7esW%(g600H3P%E4Q>2DNI4S z;8)ccjwlZ0>;P~K9#$KP@vBHtMQ~7Ei6e^B>gGJK4BuO9#CUxQBgj$+th92=av+6e zQKiseZPg&|;>hgM7+sXY0NDy)z-m^c6ESSPH4Lta^zHs!0v4pOOi~B0Pum(1zp1et z?RFD05fn(-)WB;dy)(=dlQ1>B(KoK1eH~Z}gqdwm+k~GF$VN98oUEB~O}P@{&U8JF zx+wdOkgS!@Hi^cKGhyK zc|>;hQ-)fqkc%0ihU<#;Mtc+Dod>O;oG+AV7w3p{u|2RSPP@WB6p|%XLcU<*Lb9fo z!y{g{9k$0cwU6hjLG}Na6f>JzCft_Po7l1OvBK`9LjEvaLhz+>5OziI3yRf z@LilHrjP0qV$tFtVUawtwnOkv_$M7RrT0rYf2@DDf74j`R_BasJH&aZB?m0PFE48d zX!yHE`${>E)+iobslWjRZ>%0vZt1F0n2IchFILath+_F#UE29K{y96G+ekaRnD=Vk zV|j=^?oDi0iD~s=GMTFhD?aYgMXo?=3d<&S?2l}42}jA&kP18k;1p}7fRRXBRGD>C Uz>$8!(g_MYQG;Ks!3>)I0Ot@EF8}}l diff --git a/__pycache__/ChanKLU.cpython-312.pyc b/__pycache__/ChanKLU.cpython-312.pyc index c332c16a1c7550b8df13138f909b37408efd8827..0729e0d025a7e1304d723e72376d9c160c4f1f81 100644 GIT binary patch delta 151 zcmcaqd%TwWG%qg~0}%X9wA#qs%`EGnA6lGRRIHzsn4GQelAm0fo0?ZrtnZ##;!&Ek zc@?v@0ORt>&xDPcrb$dz5Yb^~5R%&LFQUuL$T7KA+=2O;n8D_)72#QUpm@E&mg;hrnY>Syr Mf)L}c$SdT}H1c)0i~n-nVL^(8Mt2-&JqO~@pwOkUcEY>r6R;k@W$hdc?PGCVwQ;FAU^W{@Ji z*9`6yODD?~?+ydA9x#8u49naZ1dNZ)qeY719uNt~-H()Pv{ zuM5|zx$;+4HCeC{SB5Gy2E4wc5|4x?bqqf;6{?K;|6w?ihN76EC`vKB8H^{EPaBxF z4914Kd<{c>sxBKe4tZaFjRDN~c*8O_VfNy=hL2ceDU&A}Z{{%lnKd&lJgeE3XnC8b zwxtA=?^YQ}Lmpq#kxP+N79=@-ifw&)_|!S=ggv;mC6T3?iF48v$bN*TljFrJZB46&I@9=hHfjXxScMiRrDWP z=Z4LA&zXDK8}xJX%-1ZNbgq`CrdBZqS(%~`{hi*)Ph_kW|$@Mtr1mtXkcn2p(Q zBq0m<@DEb!XkGpIjnwOGQe1@}xuvp5YQWyxp}XIOc+c%QU0buXg=#Hyjt|c+T{0kP z4d6)np1Wcp{!4n!q=~6V86?!o7e4RLVUB{nk=*+AJ-{w<`6OR}ptJ65-E{NW=4*!5 z6s0RjWg(M;wg!%v-14XYZm~ci30k0^qE(Y$SzrU3kk*m31%6>bj#eN)=b%=X&T;T^ zMr!3@E0tE0r>)>7vphUY^%fv&tl<4dAGK;ysu>A2OX~pfI!ue1zGwiF%7_|(@-qR> z8(e<|y{|MM=Q*A}EJC<~wk7G5pqWkB0%WfPju~&|B72a0&!O#-(T-cGk}@G)c& zqn)Anoe;=|Ve+^Kw8QLEe&T^mj8sqVZj8J932QAG=?0&Kgh1MUcSJ4p$6d7vYkVc4VA=D5T8z;=;hSBzD@2j1s%;BIaHhy9j zC~!M2N|=|Cs$Muvfr~X@Nx9hzM>Jq59YVZQ11<%!&<8ehsUO~?=+1ONLtl}!l@W@5 zOz{msIXIBr_dkBMur}@rB&h^({(zydZW__>d$0{YBSSmkJM@hBl(C&46~J}n%nLAOgwy2d2t<4f)xkI)I^i2D zdueaf@bZCiU${!;L*JD3G3-g0i%IoCn5Hh3q^oJqkUIzA8Z}8wm(uf1s7W5>&MR<| z+Q2(*w*kuHKC(82SAIf`TAQ?&Dbu5Ho!-oOK63b%u$^|ipZtS>ixd&~oroN@xBMu} zIWLtbC4WrvC!~Njyo^PTAQ7VQyeHN@6mQ%?pK3?vOxJA5JAG%jsGHhj_qD6tLoxDJ z6nbb-eU*y@UxOxXsj~Amn6S}wOW%Yp2J*@CzlF>6&MF~~o`hZz38iU~wr<2W`cRaQ zixo+8rSjfMa5C(o;3P}5;{{}MEzz@*_o0{{{_&!{fYeSvJS`X`{(fh<+&U2r#s z>Z*#1)k$-Wa%BQaGC}Uh-wxt%hxcniLX)sk53*wtTIqjae*n^u Bp)3FZ delta 2513 zcmY*bYj6|S6~0GzB}F36DZt zCKVw}LLP(QV%CL}A%&)Nh9=-`qe9Fhfd;oGL1qU~DVbylneeBuNKV>j+R$@XxKRDr z^X)y4d%kdZd~x1mvtToYZd&Wly1Ji%Dy%XOP0DUV-i-qD;UCK_Z1%~ceonlz6yIW`#fsXR}b z2($&5U|k__pmtl|1L>)(R`hc1BsM8`4&}1&Za_Vd+e97dQGEvWJ;1&cKSyr_kLL%} zn^MRmZM`2qhfZdaYa`|I+rI|XgRTJy_OQ+|7p$7IGD8AFEvt@Js`E>h0_897hrJ=x zqzMSY*!q+pT@k#)f;ZlENeJi^7u8$grv+$Zi(1FB%@u`K%~6pdF6v|ZD*jEm{AK0M zNt3e~I9#!6gC@|4u_Y-gUZL_ZmE%9W;;k9>)*PCnd83!;1dK~3vRmPNb*QS&0yB0- zE3(ua9S`$jWhU5m5rof1qxP0->H#~hEdyDQRTE-LgT@gaVLZ}ZDE#--peP#=w zy>Ti}PS_{Fd?V#xeL*&54_2eGJ_jfVEe+!YaI$BbimjTxG)+R(&EiehDN1$yw3}8~ zi_Ue{l<3Wn99qD7TTjX;btfsnO}qw2GkpSB=OYUR4%GJ_Ipc*Ewspb7Hq>UwV-&af z^Mczsf`Q)a%8_9kJG1dIn`SS`kRG6gs`Q-SA{eOh=XG+?mK@$zsXQrGkrG|lSxz}N z&PZV$rN!zx)}A96=)#^^0qA6f@7CE;k}pH%n}o31_U^aTs`+PT$QZjropXGui6UU} zfoiMfZOM=#TUb3Yu%EgS=s%;}NAD3xt}7N{JI)5wS56mDc_dp$uRm#W8zd!K#`@2+ zVR>rP#4LoFo4$Y|8nu>fy6NDx1K_-d5p9rTF$PVTX^5OVKD2w zeXyLOQcVm#Z^AOv4@Iy>fYuNIkk0?sD;rwi_+ww8jjpe!s`~AmU7g1ll&~AfL zERoM8I`E*3)8e)AVIA+LzA~fKBkW|CUv*v;spr(a5i)FX&Lk}9-ISlTe6k%$6d(yS zWp7`#sb7C`z-8(+v*Tg;#d1{78W;se=+MN{Owoixu|N*5T{{Z&WbaCq8#7MOd3^;`kc>25B*6K-$-?SwcKiY3owOp zb>Dv`fh{E#@Jr>ppv-bWt+W1E{i)_-&6kAPx|y%4?z=1UOpO9}VApT^l|R}6YwoDd zkTM!pzOcjN*a5S!e3r0Mp9kA12b(1bDqrM*>%Q(^dGNZSdqspF;quI^%a4F&AhFW{p9-N{*}lkDO2TsGIkCg}khrN+*(O7? zRdYq~_A?hMLo)oDa;IEo)029(4%Y$0l%2aGsI7W ziC=`E%|to+dodiG0-40l4mbi;sYt_RcjNx9U5$M+d#5Mejj{3g7_pE%*DgPu+wDfPMll_e*-t7ks9I-^wn#waE6Sd z=EPf1!8r&Z8fgdO^v2uXpnc!h@@q85_%yN7Zctw6gz_LqBkp?!$zY9^KVEa-L0IWV zPzKOKFwl)o7=uk9r-_9=YEp8Rz<^+&50^l+A{A}AEKfTm>}v1p>RptSr^RaVal`IJ zPVFqD*^9HB3YJ3uC?_L-SwT*Bls!KNmvX5K_8R1(MDk||Be^he?Eo^AM^z9I@N>$fhmZJO1Ufb9w zy#9PripHw&G1?9ttVpwuNn?xpl+1QGB_hzPi74X*K>f<`I9w7D=wZTd;7aOH@W6@^ zf7k(ULjYgX^MF{y>yGKMDL3%s9@X4tZ1$t6d9fp8VFuP>Hxyeq(j&^7rSQ`-YI&(*bH&S5@s9n^B$uqdJniY^ z!bPV$2TML!c5H64t$p~R_KV6Q1(xE}Vi23)=bHqSPZemQ_?8Iu!BH2U%Z1-UrwOJh z6Ar@=&QVDkKYGQ=-NVpTfM7(%35mOQ&FGUfxk9t!--vpeo7nI>@SChDr$0?-j->2( z2g3<=Q_rnw(Qu(?cW>cQdOcnk~;Tz?l1g!rr$Rq(z diff --git a/__pycache__/ChanSBI.cpython-312.pyc b/__pycache__/ChanSBI.cpython-312.pyc index 143d5236730e0878382392f046422aa6324ec6a5..39238c4f1ffb050951849e99d129db3e54299dea 100644 GIT binary patch delta 62 zcmbO&w?vNTG%qg~0}vee$Cj~?hn-p0K|i!OwWwG>D=|4+-z7h}G&eP`q*&iQv&5q` RX|p=>7H-B{lkf1^0{}_k6jlHL delta 53 zcmZ1?H(QS9G%qg~0}x33c#^)6hn-o(TtBopwWwG>D=|4+KcFZ-D>b=fvjOuKZpL4e IpYquQ0H(eXSO5S3 diff --git a/__pycache__/ChanSEG.cpython-312.pyc b/__pycache__/ChanSEG.cpython-312.pyc index dac2f10047089de9ff297a3c17e2a5e859e70458..309ff0782713bb4b28e1d3dcbfc97828a88adebc 100644 GIT binary patch delta 61 zcmbO(y+E4#G%qg~0}$wB@@(W@&MfPoA6lGRRIHzsn4GQelAm0fo0?ZrtnZ##;!&Ek P`55yAPR3i4!+9M57oZbQ delta 52 zcmZ1=JzbjnG%qg~0}xEKW8cWVoLR(NKeRZts8~NMF*#d5peR2pHMwN-dFBb6jK3x) H@HzkhfAbJm diff --git a/__pycache__/ChanZS.cpython-312.pyc b/__pycache__/ChanZS.cpython-312.pyc index c3d36260054d9b1db64876f3ccd38ebbf403a195..db18ccb2faa8a093d385403355f16a701fe64021 100644 GIT binary patch delta 62 zcmca2dsmj{G%qg~0}vee$Cj~?=OweOy?$tMYEiL%R$_9tzDs^`X>Mv>NwL0rW{F2> R(q>MU$y|)LCeP(F2LOj^6(Ils delta 53 zcmcaBdqtM#G%qg~0}$xU{+_;(=Owd 0: + # 添加小周期技术指标(包括布林带) + element_df = add_indicators(element_df) + # 对小周期数据进行缠论分析 element_analysis = analyze_chan(element_df) @@ -692,6 +710,18 @@ def analyze(): result['element_timeframe'] = element_timeframe result['element_macd'] = element_macd_data # 添加小周期MACD数据 + # 添加小周期布林带数据 + result['element_bollinger'] = { + 'upper': element_df['bb_upper'].tolist(), + 'middle': element_df['bb_middle'].tolist(), + 'lower': element_df['bb_lower'].tolist() + } + result['element_element_bollinger'] = { + 'upper': element_df['element_bb_upper'].tolist(), + 'middle': element_df['element_bb_middle'].tolist(), + 'lower': element_df['element_bb_lower'].tolist() + } + result['element_bi_list'] = [{ 'start_time': bi.start_klc.end_time if isinstance(bi.start_klc.end_time, str) else bi.start_klc.end_time.astimezone(client_tz).isoformat(), 'end_time': (bi.end_klc.end_time if isinstance(bi.end_klc.end_time, str) else bi.end_klc.end_time.astimezone(client_tz).isoformat()) if bi.end_klc else None, @@ -720,7 +750,6 @@ def analyze(): 'is_sure': zs.is_sure # 添加中枢是否完成的标志 } for zs in element_analysis['zs_list'] if zs.end_klc] - # 添加小周期未完成中枢列表 result['element_uncompleted_zs_list'] = [{ 'start_time': zs.start_klc.end_time if isinstance(zs.start_klc.end_time, str) else zs.start_klc.end_time.astimezone(client_tz).isoformat(), 'end_time': None, # 未完成中枢没有结束时间 diff --git a/web/templates/index.html b/web/templates/index.html index e4860b3..ca2a1a1 100644 --- a/web/templates/index.html +++ b/web/templates/index.html @@ -327,7 +327,7 @@ {% endfor %} -
+
-
+
-
+
- +
-
+
@@ -397,6 +399,10 @@
+
+ + +
@@ -424,22 +430,25 @@
+
+ + +
-
-
- - {% for value, label in timeframes.items() %} {% endfor %} - 仅影响笔、线段和中枢分析
-
- - @@ -450,18 +459,18 @@ -
+
- +
-
- - @@ -479,8 +488,8 @@ 停止
- - @@ -733,7 +742,9 @@ elementSegSeries: [], elementZsSeries: [], elementUncompletedZsSeries: [], - tradePointSeries: [] + tradePointSeries: [], + mainBollingerSeries: [], + elementBollingerSeries: [] }, state: { isInitialized: false, @@ -955,6 +966,15 @@ refreshChartOnly(); }); + // 添加布林带显示变更事件 + $('#showMainBollinger').change(function() { + updateChartDisplay(); + }); + + $('#showElementBollinger').change(function() { + updateChartDisplay(); + }); + // 添加K线周期切换事件监听器 $('input[name="klinePeriod"]').change(function() { console.log('K线周期切换:', $(this).attr('id'), $(this).is(':checked')); @@ -1055,6 +1075,8 @@ console.log('- 显示小周期分型:', $('#showElementKlcFxType').is(':checked')); console.log('- 显示买卖点:', $('#showTradePoints').is(':checked')); console.log('- 显示原始K线:', $('#showOriginalKline').is(':checked')); + console.log('- 显示主周期布林带:', $('#showMainBollinger').is(':checked')); + console.log('- 显示次周期布林带:', $('#showElementBollinger').is(':checked')); // 重新初始化图表,这将清除旧图形并重新绘制 initTradingView($('#symbol').val(), $('#timeframe').val()); @@ -1302,7 +1324,9 @@ elementSegSeries: [], elementZsSeries: [], elementUncompletedZsSeries: [], - tradePointSeries: [] + tradePointSeries: [], + mainBollingerSeries: [], + elementBollingerSeries: [] }, state: { isInitialized: false, @@ -1914,33 +1938,32 @@ // 在笔的末端添加macd_div值标记 if (bi.macd_div && bi.macd_div !== 0 && $('#showMainMacdDiv').is(':checked')) { - console.log(`添加macd_div标记: ${bi.macd_div.toFixed(2)}, 在时间点: ${endTime}`); + console.log(`添加主周期macd_div标记: ${bi.macd_div.toFixed(2)}, 在时间点: ${endTime}`); const macdDivLabel = mainChart.addLineSeries({ lastValueVisible: false, priceLineVisible: false, + color: 'transparent', // 设置为透明色 + lineWidth: 0, // 线宽为0 }); - // 确定标记位置 - const markerPosition = bi.direction === 1 ? 'aboveBar' : 'belowBar'; - const labelValue = bi.direction === 1 ? endPrice + (endPrice * 0.005) : endPrice - (endPrice * 0.005); - const arrayShape = bi.direction === 1 ? 'arrowDown' : 'arrowUp'; - // 简化标记显示 + // 添加一个透明的数据点用于承载标记 macdDivLabel.setData([ - { time: endTime, value: labelValue } + { time: endTime, value: endPrice } ]); - // 使用不同方式添加文本标记 + // 主周期MACD背离标记根据笔方向显示,远离K线避免与分型重叠 + const markerPosition = bi.direction === 1 ? 'aboveBar' : 'belowBar'; const textColor = bi.macd_div > 0 ? '#dc3545' : '#28a745'; - const textSize = Math.min(14, Math.max(10, Math.abs(bi.macd_div) * 2)); + // 只使用标记,不添加数据点 macdDivLabel.setMarkers([ { time: endTime, position: markerPosition, color: textColor, - shape: arrayShape, - text: bi.macd_div.toFixed(2), + text: `${bi.macd_div.toFixed(2)}`, // 添加M前缀区分 + size: 0.6, // 更小的尺寸,远离分型标记 } ]); } @@ -1998,29 +2021,27 @@ const macdDivLabel = mainChart.addLineSeries({ lastValueVisible: false, priceLineVisible: false, + color: 'transparent', // 设置为透明色 + lineWidth: 0, // 线宽为0 }); - // 确定标记位置 - const markerPosition = bi.direction === 1 ? 'aboveBar' : 'belowBar'; - const labelValue = bi.direction === 1 ? endPrice + (endPrice * 0.005) : endPrice - (endPrice * 0.005); - const arrayShape = bi.direction === 1 ? 'arrowDown' : 'arrowUp'; - // 简化标记显示 + // 添加一个透明的数据点用于承载标记 macdDivLabel.setData([ - { time: endTime, value: labelValue } + { time: endTime, value: endPrice } ]); - // 使用不同方式添加文本标记 + // 次周期MACD背离标记使用不同位置,进一步避免重叠 + const markerPosition = bi.direction === 1 ? 'aboveBar' : 'belowBar'; const textColor = bi.macd_div > 0 ? '#9c27b0' : '#673ab7'; - const textSize = Math.min(14, Math.max(10, Math.abs(bi.macd_div) * 2)); + // 只使用标记,不添加数据点 macdDivLabel.setMarkers([ { time: endTime, position: markerPosition, - color: textColor, - shape: arrayShape, - text: bi.macd_div.toFixed(2), - transparent: true, + color: textColor, + text: `${bi.macd_div.toFixed(2)}`, // 添加E前缀区分次周期 + size: 0.4, // 更小的尺寸,让分型标记有更多空间 } ]); } @@ -2977,6 +2998,171 @@ console.log('绘制买卖点 - 已禁用'); } + // 绘制布林带 + if ($('#showMainBollinger').is(':checked') || $('#showElementBollinger').is(':checked')) { + console.log('绘制布林带 - 已启用'); + + // 主周期布林带 + if ($('#showMainBollinger').is(':checked') && currentData.bollinger && currentData.bollinger.upper && currentData.bollinger.lower && currentData.bollinger.middle) { + console.log(`绘制主周期布林带数据,共${currentData.bollinger.upper.length}条`); + + // 准备布林带数据 + const upperBandData = []; + const lowerBandData = []; + const middleBandData = []; + + // 主周期布林带始终使用主周期K线数据作为时间源 + const mainKlineData = currentData.kline_data; + + for (let i = 0; i < mainKlineData.length && i < currentData.bollinger.upper.length; i++) { + const kline = mainKlineData[i]; + const timestamp = Math.floor(new Date(kline.date).getTime() / 1000); + + // 只添加非0的有效数据点 + if (currentData.bollinger.upper[i] && currentData.bollinger.upper[i] !== 0) { + upperBandData.push({ + time: timestamp, + value: currentData.bollinger.upper[i] + }); + } + + if (currentData.bollinger.lower[i] && currentData.bollinger.lower[i] !== 0) { + lowerBandData.push({ + time: timestamp, + value: currentData.bollinger.lower[i] + }); + } + + if (currentData.bollinger.middle[i] && currentData.bollinger.middle[i] !== 0) { + middleBandData.push({ + time: timestamp, + value: currentData.bollinger.middle[i] + }); + } + } + + // 创建布林带上轨 + const upperBandSeries = mainChart.addLineSeries({ + color: '#2196F3', + lineWidth: 1, + lineStyle: 2, // 虚线 + lastValueVisible: false, + priceLineVisible: false, + title: '布林上轨' + }); + upperBandSeries.setData(upperBandData); + + // 创建布林带下轨 + const lowerBandSeries = mainChart.addLineSeries({ + color: '#2196F3', + lineWidth: 1, + lineStyle: 2, // 虚线 + lastValueVisible: false, + priceLineVisible: false, + title: '布林下轨' + }); + lowerBandSeries.setData(lowerBandData); + + // 创建布林带中轨(移动平均线) + const middleBandSeries = mainChart.addLineSeries({ + color: '#FF9800', + lineWidth: 1, + lastValueVisible: false, + priceLineVisible: false, + title: '布林中轨' + }); + middleBandSeries.setData(middleBandData); + + // 保存到tvWidget.series对象 + tvWidget.series.mainBollingerSeries.push(upperBandSeries); + tvWidget.series.mainBollingerSeries.push(lowerBandSeries); + tvWidget.series.mainBollingerSeries.push(middleBandSeries); + + console.log('主周期布林带绘制完成'); + } + + // 次周期布林带 + if ($('#showElementBollinger').is(':checked') && currentData.element_bollinger && currentData.element_bollinger.upper && currentData.element_bollinger.lower && currentData.element_bollinger.middle) { + console.log(`绘制次周期布林带数据,共${currentData.element_bollinger.upper.length}条`); + + // 准备次周期布林带数据 + const elementUpperBandData = []; + const elementLowerBandData = []; + const elementMiddleBandData = []; + + // 使用次周期K线数据 + const elementKlineData = currentData.element_kline_data || currentData.kline_data; + + for (let i = 0; i < elementKlineData.length && i < currentData.element_bollinger.upper.length; i++) { + const kline = elementKlineData[i]; + const timestamp = Math.floor(new Date(kline.date).getTime() / 1000); + + // 只添加非0的有效数据点 + if (currentData.element_bollinger.upper[i] && currentData.element_bollinger.upper[i] !== 0) { + elementUpperBandData.push({ + time: timestamp, + value: currentData.element_bollinger.upper[i] + }); + } + + if (currentData.element_bollinger.lower[i] && currentData.element_bollinger.lower[i] !== 0) { + elementLowerBandData.push({ + time: timestamp, + value: currentData.element_bollinger.lower[i] + }); + } + + if (currentData.element_bollinger.middle[i] && currentData.element_bollinger.middle[i] !== 0) { + elementMiddleBandData.push({ + time: timestamp, + value: currentData.element_bollinger.middle[i] + }); + } + } + + // 创建次周期布林带上轨 + const elementUpperBandSeries = mainChart.addLineSeries({ + color: '#9C27B0', + lineWidth: 1, + lineStyle: 2, // 虚线 + lastValueVisible: false, + priceLineVisible: false, + title: '次周期布林上轨' + }); + elementUpperBandSeries.setData(elementUpperBandData); + + // 创建次周期布林带下轨 + const elementLowerBandSeries = mainChart.addLineSeries({ + color: '#9C27B0', + lineWidth: 1, + lineStyle: 2, // 虚线 + lastValueVisible: false, + priceLineVisible: false, + title: '次周期布林下轨' + }); + elementLowerBandSeries.setData(elementLowerBandData); + + // 创建次周期布林带中轨 + const elementMiddleBandSeries = mainChart.addLineSeries({ + color: '#E91E63', + lineWidth: 1, + lastValueVisible: false, + priceLineVisible: false, + title: '次周期布林中轨' + }); + elementMiddleBandSeries.setData(elementMiddleBandData); + + // 保存到tvWidget.series对象 + tvWidget.series.elementBollingerSeries.push(elementUpperBandSeries); + tvWidget.series.elementBollingerSeries.push(elementLowerBandSeries); + tvWidget.series.elementBollingerSeries.push(elementMiddleBandSeries); + + console.log('次周期布林带绘制完成'); + } + } else { + console.log('绘制布林带 - 已禁用'); + } + // 绘制分型类型标签 console.log('=== 开始检查分型显示条件 ==='); console.log('showKlcFxType勾选状态:', $('#showKlcFxType').is(':checked')); @@ -3034,8 +3220,8 @@ is_strong_fx: fx.is_strong_fx }); let displayText = `${fx.fx_strength_level} ${fx.fx_strength.toFixed(1)}`; - if (fx.fx_strength < 1.4) { - displayText = '' + if (fx.fx_strength < 1.0) { // 降低阈值,让更多分型显示 + displayText = fx.fx_strength >= 0.8 ? '•' : '' // 0.8以上显示点,0.8以下不显示文本 } console.log('显示文本:', displayText); @@ -3044,9 +3230,9 @@ time: timestamp, position: fx.is_bottom ? 'belowBar' : 'aboveBar', color: strengthColor, - shape: fx.is_strong_fx ? 'square' : 'circle', + shape: 'circle', text: displayText, - size: fx.is_strong_fx ? 2 : 1 + size: fx.is_strong_fx ? 1 : 0.6 // 调整尺寸,强分型稍大,普通分型更小 }; console.log('标记配置:', markerConfig); @@ -3125,8 +3311,8 @@ } let displayText = `${fx.fx_strength_level} ${fx.fx_strength.toFixed(1)}`; // 构建小周期分型显示文本 - if (fx.fx_strength < 1){ - displayText = '' + if (fx.fx_strength < 0.8){ // 调整小周期阈值 + displayText = fx.fx_strength >= 0.6 ? '•' : '' // 0.6以上显示点 } // 小周期分型标记配置 - 根据分型类型使用正确的箭头形状 @@ -3134,8 +3320,9 @@ time: timestamp, position: fx.is_bottom ? 'belowBar' : 'aboveBar', color: strengthColor, + shape: 'circle', text: displayText, - size: fx.is_strong_fx ? 2 : 1 + size: fx.is_strong_fx ? 0.8 : 0.6 // 小周期标记整体更小一些 }; console.log('小周期分型标记配置:', markerConfig); @@ -4353,7 +4540,9 @@ elementSegSeries: [], elementZsSeries: [], elementUncompletedZsSeries: [], - tradePointSeries: [] + tradePointSeries: [], + mainBollingerSeries: [], + elementBollingerSeries: [] }; } catch (e) { console.error('销毁图表错误:', e); @@ -4797,6 +4986,15 @@ refreshChart(currentData); }); + // 绑定布林带显示变更事件 + $('#showMainBollinger').change(function() { + updateChartDisplay(); + }); + + $('#showElementBollinger').change(function() { + updateChartDisplay(); + }); + // 绑定K线周期切换 $('input[name="klinePeriod"]').change(function() { refreshChart(currentData); @@ -4814,6 +5012,8 @@ 'showKlcFxType': $('#showKlcFxType').is(':checked'), 'showElementKlcFxType': $('#showElementKlcFxType').is(':checked'), 'showTradePoints': $('#showTradePoints').is(':checked'), + 'showMainBollinger': $('#showMainBollinger').is(':checked'), + 'showElementBollinger': $('#showElementBollinger').is(':checked'), 'timeframe': $('#timeframe').val(), 'elementTimeframe': $('#elementTimeframe').val(), 'timezone': $('#timezone').val(),