From 05a60cf0d457ff272a2c03cf6c44a202a790530d Mon Sep 17 00:00:00 2001 From: hmo Date: Tue, 21 Jul 2026 23:24:45 +0800 Subject: [PATCH] =?UTF-8?q?revert(34337fc5):=20=E6=81=A2=E5=A4=8D=E8=A2=AB?= =?UTF-8?q?=E7=9F=A5=E5=BE=AE=E4=BA=8C=E6=AC=A1stale=E6=8F=90=E4=BA=A4?= =?UTF-8?q?=E8=A6=86=E7=9B=96=E7=9A=84=E6=98=A8=E6=99=9A=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E2=80=94=E2=80=94batch/per=5Fstock/stale=5Fdetector/fix=5Fgate?= =?UTF-8?q?way=5Fport/candidate=5Ffilter=20=E5=9B=9E=E6=BB=9A=E8=87=B31e71?= =?UTF-8?q?a2d8=E7=89=88=E6=9C=AC=EF=BC=9B=E5=A5=B9=E6=8F=90=E4=BA=A4?= =?UTF-8?q?=E4=B8=AD=E7=9A=84=E8=BF=90=E8=A1=8C=E6=97=B6=E6=96=87=E4=BB=B6?= =?UTF-8?q?(db-shm/db-wal/price=5Fhistory/market=5Fscan=5Fsummary)?= =?UTF-8?q?=E7=A7=BB=E5=87=BA=E8=B7=9F=E8=B8=AA=EF=BC=9B=E4=BF=9D=E7=95=99?= =?UTF-8?q?=E5=85=B6morning=5Fhealth=5Fcheck=E5=B0=8F=E6=9E=9C=E6=B8=85?= =?UTF-8?q?=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 5 + data/mofin.db-shm | Bin 32768 -> 0 bytes data/mofin.db-wal | 0 data/price_history.json | 2404 ----------------- deploy/profile-scripts/batch_reassess.py | 261 +- deploy/profile-scripts/candidate_filter.py | 4 +- .../data/market_scan_summary.json | 7 - deploy/profile-scripts/fix_gateway_port.py | 43 +- deploy/profile-scripts/per_stock_reassess.py | 129 +- deploy/profile-scripts/stale_detector.py | 22 +- 10 files changed, 332 insertions(+), 2543 deletions(-) delete mode 100644 data/mofin.db-shm delete mode 100644 data/mofin.db-wal delete mode 100644 data/price_history.json delete mode 100644 deploy/profile-scripts/data/market_scan_summary.json diff --git a/.gitignore b/.gitignore index 8ec8b65f..4496f22c 100644 --- a/.gitignore +++ b/.gitignore @@ -39,3 +39,8 @@ scripts/mo_data.py data/prompts/ data/backups/ + +data/mofin.db-shm +data/mofin.db-wal +data/price_history.json +deploy/profile-scripts/data/ diff --git a/data/mofin.db-shm b/data/mofin.db-shm deleted file mode 100644 index 6aecbd297b2141bc7de0c2e9bbeb3ee11b3cb021..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32768 zcmeI*u?Ye(6b9gTimg~4?qKZ_Ru+zMn_Me6fQ5~{1Gs>ly@d#lV11Ve0b7e}j_-%Z zOF~HC8z8A)tH_z8sv;J7d|pOuc9+@b(Z17kzCE07_h+=%=D4r_+@H@Y>3&kyN?)hJ zG*#|GfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PF{(AisDd1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72n;Jweg6R&_70~LAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlq Gr$7&sawkRr diff --git a/data/mofin.db-wal b/data/mofin.db-wal deleted file mode 100644 index e69de29b..00000000 diff --git a/data/price_history.json b/data/price_history.json deleted file mode 100644 index f4679c9e..00000000 --- a/data/price_history.json +++ /dev/null @@ -1,2404 +0,0 @@ -{ - "688772": [ - { - "date": "2026-07-15", - "high": 15.94, - "low": 15.1, - "close": 15.4, - "volume": 25649705.0, - "amount": 39697.0 - }, - { - "date": "2026-07-16", - "high": 16.24, - "low": 15.1, - "close": 15.59, - "volume": 32009925.0, - "amount": 50554.0 - }, - { - "date": "2026-07-17", - "high": 16.24, - "low": 14.1, - "close": 14.21, - "volume": 37396292.0, - "amount": 55424.0 - }, - { - "date": "2026-07-19", - "high": 15.75, - "low": 14.1, - "close": 14.21, - "volume": 37396292.0, - "amount": 55424.0 - }, - { - "date": "2026-07-20", - "high": 15.75, - "low": 13.05, - "close": 13.41, - "volume": 41864386.0, - "amount": 56681.0 - }, - { - "date": "2026-07-21", - "high": 13.98, - "low": 13.05, - "close": 13.88, - "volume": 21053573.0, - "amount": 28442.0 - } - ], - "688775": [ - { - "date": "2026-07-15", - "high": 133.4, - "low": 126.86, - "close": 130.33, - "volume": 2801575.0, - "amount": 36613.0 - }, - { - "date": "2026-07-16", - "high": 149.6, - "low": 126.86, - "close": 147.3, - "volume": 8061165.0, - "amount": 115238.0 - }, - { - "date": "2026-07-17", - "high": 149.6, - "low": 128.99, - "close": 138.34, - "volume": 6157193.0, - "amount": 86656.0 - }, - { - "date": "2026-07-19", - "high": 149.0, - "low": 135.76, - "close": 138.34, - "volume": 6157193.0, - "amount": 86656.0 - }, - { - "date": "2026-07-20", - "high": 149.0, - "low": 129.5, - "close": 136.32, - "volume": 4713131.0, - "amount": 63136.0 - }, - { - "date": "2026-07-21", - "high": 135.31, - "low": 127.44, - "close": 129.94, - "volume": 3284644.0, - "amount": 42769.0 - } - ], - "688475": [ - { - "date": "2026-07-15", - "high": 27.57, - "low": 26.35, - "close": 27.31, - "volume": 6126416.0, - "amount": 16688.0 - }, - { - "date": "2026-07-16", - "high": 28.0, - "low": 26.35, - "close": 27.15, - "volume": 5897212.0, - "amount": 16260.0 - }, - { - "date": "2026-07-17", - "high": 28.0, - "low": 26.4, - "close": 26.64, - "volume": 5999240.0, - "amount": 16223.0 - }, - { - "date": "2026-07-19", - "high": 27.74, - "low": 26.4, - "close": 26.64, - "volume": 5999240.0, - "amount": 16223.0 - }, - { - "date": "2026-07-20", - "high": 27.78, - "low": 26.4, - "close": 27.73, - "volume": 6881480.0, - "amount": 18584.0 - } - ], - "688778": [ - { - "date": "2026-07-15", - "high": 48.36, - "low": 46.4, - "close": 46.79, - "volume": 8820199.0, - "amount": 41519.0 - }, - { - "date": "2026-07-16", - "high": 48.36, - "low": 45.81, - "close": 46.28, - "volume": 8566628.0, - "amount": 40052.0 - }, - { - "date": "2026-07-17", - "high": 47.6, - "low": 44.09, - "close": 44.14, - "volume": 7684619.0, - "amount": 34599.0 - }, - { - "date": "2026-07-19", - "high": 46.45, - "low": 44.09, - "close": 44.14, - "volume": 7684619.0, - "amount": 34599.0 - }, - { - "date": "2026-07-20", - "high": 46.45, - "low": 42.05, - "close": 43.0, - "volume": 9254116.0, - "amount": 40066.0 - }, - { - "date": "2026-07-21", - "high": 45.54, - "low": 42.81, - "close": 45.23, - "volume": 7045084.0, - "amount": 31399.0 - } - ], - "688501": [ - { - "date": "2026-07-15", - "high": 17.99, - "low": 17.26, - "close": 17.7, - "volume": 1264045.0, - "amount": 2237.0 - }, - { - "date": "2026-07-16", - "high": 17.99, - "low": 17.15, - "close": 17.61, - "volume": 1388168.0, - "amount": 2440.0 - }, - { - "date": "2026-07-17", - "high": 17.8, - "low": 16.64, - "close": 16.79, - "volume": 1904231.0, - "amount": 3272.0 - }, - { - "date": "2026-07-19", - "high": 17.8, - "low": 16.64, - "close": 16.79, - "volume": 1904231.0, - "amount": 3272.0 - }, - { - "date": "2026-07-20", - "high": 17.8, - "low": 15.42, - "close": 15.91, - "volume": 2834080.0, - "amount": 4591.0 - } - ], - "688510": [ - { - "date": "2026-07-15", - "high": 23.27, - "low": 21.69, - "close": 22.3, - "volume": 6687750.0, - "amount": 15095.0 - }, - { - "date": "2026-07-16", - "high": 23.5, - "low": 21.69, - "close": 22.21, - "volume": 4866983.0, - "amount": 11018.0 - }, - { - "date": "2026-07-17", - "high": 23.5, - "low": 20.63, - "close": 21.0, - "volume": 5596808.0, - "amount": 12011.0 - }, - { - "date": "2026-07-19", - "high": 22.46, - "low": 20.63, - "close": 21.0, - "volume": 5596808.0, - "amount": 12011.0 - }, - { - "date": "2026-07-20", - "high": 22.46, - "low": 20.25, - "close": 20.76, - "volume": 6770593.0, - "amount": 14184.0 - } - ], - "688513": [ - { - "date": "2026-07-15", - "high": 65.0, - "low": 57.02, - "close": 60.09, - "volume": 6013480.0, - "amount": 36538.0 - }, - { - "date": "2026-07-16", - "high": 65.0, - "low": 57.02, - "close": 58.58, - "volume": 3762256.0, - "amount": 22314.0 - }, - { - "date": "2026-07-17", - "high": 61.5, - "low": 54.5, - "close": 54.63, - "volume": 4293163.0, - "amount": 24190.0 - }, - { - "date": "2026-07-19", - "high": 59.9, - "low": 54.5, - "close": 54.63, - "volume": 4293163.0, - "amount": 24190.0 - }, - { - "date": "2026-07-20", - "high": 59.9, - "low": 53.67, - "close": 57.6, - "volume": 3704960.0, - "amount": 20838.0 - } - ], - "688518": [ - { - "date": "2026-07-15", - "high": 21.71, - "low": 20.59, - "close": 20.76, - "volume": 15732206.0, - "amount": 33155.0 - }, - { - "date": "2026-07-16", - "high": 21.71, - "low": 19.29, - "close": 19.48, - "volume": 17313602.0, - "amount": 34625.0 - }, - { - "date": "2026-07-17", - "high": 20.73, - "low": 18.31, - "close": 18.46, - "volume": 18674329.0, - "amount": 35390.0 - }, - { - "date": "2026-07-19", - "high": 19.78, - "low": 18.31, - "close": 18.46, - "volume": 18674329.0, - "amount": 35390.0 - }, - { - "date": "2026-07-20", - "high": 19.78, - "low": 16.81, - "close": 17.24, - "volume": 21448924.0, - "amount": 38124.0 - } - ], - "00700": [ - { - "date": "2026-07-15", - "high": 476.4, - "low": 455.4, - "close": 474.0, - "volume": 33780856.0, - "amount": 15912582703.396 - }, - { - "date": "2026-07-16", - "high": 494.8, - "low": 455.4, - "close": 484.0, - "volume": 35638380.0, - "amount": 17315931741.46 - }, - { - "date": "2026-07-17", - "high": 494.8, - "low": 458.0, - "close": 461.6, - "volume": 36237657.0, - "amount": 16928705332.905 - }, - { - "date": "2026-07-19", - "high": 488.8, - "low": 458.0, - "close": 461.6, - "volume": 36237657.0, - "amount": 16928705332.905 - }, - { - "date": "2026-07-20", - "high": 488.8, - "low": 458.0, - "close": 477.8, - "volume": 30822839.0, - "amount": 14678311361.3 - } - ], - "688533": [ - { - "date": "2026-07-15", - "high": 21.43, - "low": 20.88, - "close": 21.28, - "volume": 647207.0, - "amount": 1375.0 - }, - { - "date": "2026-07-16", - "high": 21.91, - "low": 20.88, - "close": 21.55, - "volume": 986707.0, - "amount": 2131.0 - }, - { - "date": "2026-07-17", - "high": 21.91, - "low": 20.4, - "close": 20.59, - "volume": 1359591.0, - "amount": 2855.0 - }, - { - "date": "2026-07-19", - "high": 21.74, - "low": 20.4, - "close": 20.59, - "volume": 1359591.0, - "amount": 2855.0 - }, - { - "date": "2026-07-20", - "high": 21.74, - "low": 19.96, - "close": 20.22, - "volume": 992552.0, - "amount": 2026.0 - }, - { - "date": "2026-07-21", - "high": 20.52, - "low": 19.98, - "close": 20.47, - "volume": 809558.0, - "amount": 1635.0 - } - ], - "01088": [ - { - "date": "2026-07-15", - "high": 42.92, - "low": 41.62, - "close": 42.92, - "volume": 12035425.0, - "amount": 513542990.88 - }, - { - "date": "2026-07-16", - "high": 43.26, - "low": 41.46, - "close": 41.68, - "volume": 11211067.0, - "amount": 470137707.88 - }, - { - "date": "2026-07-17", - "high": 43.26, - "low": 41.46, - "close": 42.4, - "volume": 13003969.0, - "amount": 547347699.16 - }, - { - "date": "2026-07-19", - "high": 42.5, - "low": 41.54, - "close": 42.4, - "volume": 13003969.0, - "amount": 547347699.16 - }, - { - "date": "2026-07-20", - "high": 43.66, - "low": 41.54, - "close": 43.6, - "volume": 11166601.0, - "amount": 483013474.62 - }, - { - "date": "2026-07-21", - "high": 43.72, - "low": 42.62, - "close": 43.0, - "volume": 3256797.0, - "amount": 140528469.52 - } - ], - "688566": [ - { - "date": "2026-07-15", - "high": 27.94, - "low": 26.6, - "close": 27.2, - "volume": 4577115.0, - "amount": 12544.0 - }, - { - "date": "2026-07-16", - "high": 27.94, - "low": 26.33, - "close": 27.0, - "volume": 3373341.0, - "amount": 9110.0 - }, - { - "date": "2026-07-17", - "high": 27.49, - "low": 25.0, - "close": 25.0, - "volume": 3344706.0, - "amount": 8599.0 - }, - { - "date": "2026-07-19", - "high": 27.11, - "low": 25.0, - "close": 25.0, - "volume": 3344706.0, - "amount": 8599.0 - }, - { - "date": "2026-07-20", - "high": 27.11, - "low": 24.81, - "close": 25.25, - "volume": 2923287.0, - "amount": 7436.0 - }, - { - "date": "2026-07-21", - "high": 25.25, - "low": 23.57, - "close": 24.08, - "volume": 2344451.0, - "amount": 5662.0 - } - ], - "01211": [ - { - "date": "2026-07-15", - "high": 88.9, - "low": 84.6, - "close": 86.95, - "volume": 18753937.0, - "amount": 1637610780.75 - }, - { - "date": "2026-07-16", - "high": 91.65, - "low": 84.6, - "close": 90.85, - "volume": 25429413.0, - "amount": 2288539475.116 - }, - { - "date": "2026-07-17", - "high": 91.65, - "low": 86.45, - "close": 88.7, - "volume": 26427225.0, - "amount": 2340941950.5 - }, - { - "date": "2026-07-19", - "high": 91.45, - "low": 87.25, - "close": 88.7, - "volume": 26427225.0, - "amount": 2340941950.5 - }, - { - "date": "2026-07-20", - "high": 91.5, - "low": 87.25, - "close": 90.15, - "volume": 18345094.0, - "amount": 1653609373.75 - } - ], - "688639": [ - { - "date": "2026-07-15", - "high": 17.7, - "low": 15.78, - "close": 17.5, - "volume": 10638914.0, - "amount": 18208.0 - }, - { - "date": "2026-07-16", - "high": 17.7, - "low": 15.78, - "close": 17.19, - "volume": 8477091.0, - "amount": 14511.0 - }, - { - "date": "2026-07-17", - "high": 17.56, - "low": 16.1, - "close": 16.14, - "volume": 10030710.0, - "amount": 16760.0 - }, - { - "date": "2026-07-19", - "high": 17.56, - "low": 16.1, - "close": 16.14, - "volume": 10030710.0, - "amount": 16760.0 - }, - { - "date": "2026-07-20", - "high": 17.56, - "low": 15.56, - "close": 15.99, - "volume": 9039229.0, - "amount": 14474.0 - }, - { - "date": "2026-07-21", - "high": 16.14, - "low": 15.63, - "close": 16.03, - "volume": 4310855.0, - "amount": 6844.0 - } - ], - "688582": [ - { - "date": "2026-07-15", - "high": 50.93, - "low": 46.01, - "close": 46.98, - "volume": 8746422.0, - "amount": 41764.0 - }, - { - "date": "2026-07-16", - "high": 50.93, - "low": 43.22, - "close": 43.56, - "volume": 9876615.0, - "amount": 44611.0 - }, - { - "date": "2026-07-17", - "high": 47.19, - "low": 38.5, - "close": 38.61, - "volume": 10970620.0, - "amount": 44852.0 - }, - { - "date": "2026-07-19", - "high": 43.8, - "low": 38.5, - "close": 38.61, - "volume": 10970620.0, - "amount": 44852.0 - }, - { - "date": "2026-07-20", - "high": 43.8, - "low": 36.01, - "close": 36.95, - "volume": 9774815.0, - "amount": 37047.0 - }, - { - "date": "2026-07-21", - "high": 38.13, - "low": 34.86, - "close": 37.95, - "volume": 7028435.0, - "amount": 25791.0 - } - ], - "01478": [ - { - "date": "2026-07-15", - "high": 7.03, - "low": 6.78, - "close": 6.88, - "volume": 6779277.0, - "amount": 46746395.06 - }, - { - "date": "2026-07-16", - "high": 7.19, - "low": 6.78, - "close": 7.01, - "volume": 5888000.0, - "amount": 41821730.0 - }, - { - "date": "2026-07-17", - "high": 7.19, - "low": 6.52, - "close": 6.67, - "volume": 7833000.0, - "amount": 52372235.0 - }, - { - "date": "2026-07-19", - "high": 7.02, - "low": 6.52, - "close": 6.67, - "volume": 7833000.0, - "amount": 52372235.0 - }, - { - "date": "2026-07-20", - "high": 7.02, - "low": 6.52, - "close": 6.73, - "volume": 4247000.0, - "amount": 28512618.0 - } - ], - "688755": [ - { - "date": "2026-07-15", - "high": 25.94, - "low": 24.67, - "close": 25.4, - "volume": 1409647.0, - "amount": 3565.0 - }, - { - "date": "2026-07-16", - "high": 25.94, - "low": 24.66, - "close": 25.59, - "volume": 1379945.0, - "amount": 3488.0 - }, - { - "date": "2026-07-17", - "high": 25.89, - "low": 23.8, - "close": 24.01, - "volume": 1862009.0, - "amount": 4574.0 - }, - { - "date": "2026-07-19", - "high": 25.89, - "low": 23.8, - "close": 24.01, - "volume": 1862009.0, - "amount": 4574.0 - }, - { - "date": "2026-07-20", - "high": 25.89, - "low": 22.97, - "close": 23.23, - "volume": 1436355.0, - "amount": 3390.0 - }, - { - "date": "2026-07-21", - "high": 23.24, - "low": 22.15, - "close": 22.61, - "volume": 783114.0, - "amount": 1765.0 - } - ], - "02202": [ - { - "date": "2026-07-15", - "high": 2.43, - "low": 2.33, - "close": 2.4, - "volume": 14073308.0, - "amount": 33666392.3 - }, - { - "date": "2026-07-16", - "high": 2.53, - "low": 2.33, - "close": 2.51, - "volume": 27804500.0, - "amount": 68782759.7 - }, - { - "date": "2026-07-17", - "high": 2.56, - "low": 2.34, - "close": 2.48, - "volume": 40325958.0, - "amount": 98037795.66 - }, - { - "date": "2026-07-19", - "high": 2.55, - "low": 2.34, - "close": 2.48, - "volume": 40325958.0, - "amount": 98037795.66 - }, - { - "date": "2026-07-20", - "high": 2.55, - "low": 2.34, - "close": 2.44, - "volume": 13295500.0, - "amount": 32619014.9 - }, - { - "date": "2026-07-21", - "high": 2.46, - "low": 2.38, - "close": 2.4, - "volume": 7926700.0, - "amount": 19045845.1 - } - ], - "688692": [ - { - "date": "2026-07-15", - "high": 240.95, - "low": 230.0, - "close": 235.22, - "volume": 1403425.0, - "amount": 33130.0 - }, - { - "date": "2026-07-16", - "high": 240.95, - "low": 228.23, - "close": 229.43, - "volume": 1127079.0, - "amount": 26213.0 - }, - { - "date": "2026-07-17", - "high": 237.51, - "low": 215.0, - "close": 215.4, - "volume": 1706538.0, - "amount": 38102.0 - }, - { - "date": "2026-07-19", - "high": 231.68, - "low": 215.0, - "close": 215.4, - "volume": 1706538.0, - "amount": 38102.0 - }, - { - "date": "2026-07-20", - "high": 231.68, - "low": 209.0, - "close": 216.1, - "volume": 1795104.0, - "amount": 38484.0 - }, - { - "date": "2026-07-21", - "high": 222.86, - "low": 213.11, - "close": 220.26, - "volume": 1149200.0, - "amount": 25212.0 - } - ], - "300750": [ - { - "date": "2026-07-15", - "high": 379.99, - "low": 363.08, - "close": 373.0, - "volume": 358493.0, - "amount": 1344022.0 - }, - { - "date": "2026-07-16", - "high": 379.99, - "low": 363.08, - "close": 366.2, - "volume": 251869.0, - "amount": 929070.0 - }, - { - "date": "2026-07-17", - "high": 375.24, - "low": 360.0, - "close": 360.0, - "volume": 512453.0, - "amount": 1884671.0 - }, - { - "date": "2026-07-19", - "high": 375.24, - "low": 360.0, - "close": 360.0, - "volume": 512453.0, - "amount": 1884671.0 - }, - { - "date": "2026-07-20", - "high": 377.6, - "low": 353.8, - "close": 376.43, - "volume": 447908.0, - "amount": 1663278.0 - } - ], - "688696": [ - { - "date": "2026-07-15", - "high": 66.17, - "low": 62.72, - "close": 65.05, - "volume": 854272.0, - "amount": 5531.0 - }, - { - "date": "2026-07-16", - "high": 67.9, - "low": 62.72, - "close": 66.98, - "volume": 1260370.0, - "amount": 8375.0 - }, - { - "date": "2026-07-17", - "high": 67.9, - "low": 62.37, - "close": 62.9, - "volume": 1185875.0, - "amount": 7647.0 - }, - { - "date": "2026-07-19", - "high": 67.39, - "low": 62.37, - "close": 62.9, - "volume": 1185875.0, - "amount": 7647.0 - }, - { - "date": "2026-07-20", - "high": 67.39, - "low": 61.5, - "close": 62.72, - "volume": 1078476.0, - "amount": 6756.0 - }, - { - "date": "2026-07-21", - "high": 63.64, - "low": 61.55, - "close": 62.61, - "volume": 706654.0, - "amount": 4414.0 - } - ], - "518880": [ - { - "date": "2026-07-15", - "high": 8.42, - "low": 8.347, - "close": 8.369, - "volume": 2283310.0, - "amount": 191207.0 - }, - { - "date": "2026-07-16", - "high": 8.42, - "low": 8.347, - "close": 8.363, - "volume": 1800219.0, - "amount": 150656.0 - }, - { - "date": "2026-07-17", - "high": 8.395, - "low": 8.256, - "close": 8.311, - "volume": 2844769.0, - "amount": 235805.0 - }, - { - "date": "2026-07-19", - "high": 8.326, - "low": 8.256, - "close": 8.311, - "volume": 2844769.0, - "amount": 235805.0 - }, - { - "date": "2026-07-20", - "high": 8.362, - "low": 8.256, - "close": 8.318, - "volume": 2007208.0, - "amount": 167139.0 - } - ], - "688708": [ - { - "date": "2026-07-15", - "high": 47.22, - "low": 46.1, - "close": 46.87, - "volume": 893097.0, - "amount": 4180.0 - }, - { - "date": "2026-07-16", - "high": 47.22, - "low": 45.56, - "close": 46.1, - "volume": 1370163.0, - "amount": 6358.0 - }, - { - "date": "2026-07-17", - "high": 47.14, - "low": 43.51, - "close": 44.09, - "volume": 1442625.0, - "amount": 6448.0 - }, - { - "date": "2026-07-19", - "high": 46.18, - "low": 43.51, - "close": 44.09, - "volume": 1442625.0, - "amount": 6448.0 - }, - { - "date": "2026-07-20", - "high": 46.18, - "low": 42.31, - "close": 44.91, - "volume": 1781103.0, - "amount": 7823.0 - }, - { - "date": "2026-07-21", - "high": 46.55, - "low": 44.23, - "close": 46.06, - "volume": 1124450.0, - "amount": 5109.0 - } - ], - "688779": [ - { - "date": "2026-07-15", - "high": 7.35, - "low": 7.07, - "close": 7.16, - "volume": 21004882.0, - "amount": 15073.0 - }, - { - "date": "2026-07-16", - "high": 7.35, - "low": 6.96, - "close": 7.01, - "volume": 23490677.0, - "amount": 16563.0 - }, - { - "date": "2026-07-17", - "high": 7.14, - "low": 6.67, - "close": 6.7, - "volume": 25020310.0, - "amount": 17115.0 - }, - { - "date": "2026-07-19", - "high": 7.03, - "low": 6.67, - "close": 6.69, - "volume": 26278826.0, - "amount": 17957.0 - }, - { - "date": "2026-07-20", - "high": 7.04, - "low": 6.67, - "close": 6.9, - "volume": 37370857.0, - "amount": 25733.0 - }, - { - "date": "2026-07-21", - "high": 7.08, - "low": 6.81, - "close": 7.0, - "volume": 23142938.0, - "amount": 16082.0 - } - ], - "300035": [ - { - "date": "2026-07-15", - "high": 13.02, - "low": 12.59, - "close": 12.64, - "volume": 127152.0, - "amount": 16215.0 - }, - { - "date": "2026-07-16", - "high": 13.02, - "low": 12.45, - "close": 12.49, - "volume": 119951.0, - "amount": 15082.0 - }, - { - "date": "2026-07-17", - "high": 12.75, - "low": 12.05, - "close": 12.08, - "volume": 158047.0, - "amount": 19469.0 - }, - { - "date": "2026-07-19", - "high": 12.68, - "low": 12.05, - "close": 12.08, - "volume": 158047.0, - "amount": 19469.0 - }, - { - "date": "2026-07-20", - "high": 12.68, - "low": 11.85, - "close": 12.09, - "volume": 186464.0, - "amount": 22594.0 - } - ], - "688789": [ - { - "date": "2026-07-15", - "high": 47.6, - "low": 45.71, - "close": 46.12, - "volume": 1252617.0, - "amount": 5811.0 - }, - { - "date": "2026-07-16", - "high": 47.6, - "low": 45.3, - "close": 46.62, - "volume": 1413842.0, - "amount": 6540.0 - }, - { - "date": "2026-07-17", - "high": 47.73, - "low": 45.19, - "close": 46.23, - "volume": 2173285.0, - "amount": 10089.0 - }, - { - "date": "2026-07-19", - "high": 47.73, - "low": 45.19, - "close": 46.1, - "volume": 2179608.0, - "amount": 10118.0 - }, - { - "date": "2026-07-20", - "high": 47.88, - "low": 45.19, - "close": 47.71, - "volume": 1814330.0, - "amount": 8528.0 - }, - { - "date": "2026-07-21", - "high": 48.73, - "low": 47.09, - "close": 47.38, - "volume": 933550.0, - "amount": 4448.0 - } - ], - "600563": [ - { - "date": "2026-07-15", - "high": 139.98, - "low": 131.0, - "close": 131.55, - "volume": 56994.0, - "amount": 76291.0 - }, - { - "date": "2026-07-16", - "high": 139.98, - "low": 127.99, - "close": 134.1, - "volume": 52087.0, - "amount": 69574.0 - } - ], - "300308": [ - { - "date": "2026-07-15", - "high": 1207.98, - "low": 1160.0, - "close": 1169.31, - "volume": 247946.0, - "amount": 2928192.0 - }, - { - "date": "2026-07-16", - "high": 1207.98, - "low": 1098.0, - "close": 1113.0, - "volume": 306634.0, - "amount": 3447419.0 - }, - { - "date": "2026-07-17", - "high": 1163.0, - "low": 956.0, - "close": 957.88, - "volume": 419591.0, - "amount": 4233073.0 - }, - { - "date": "2026-07-19", - "high": 1072.0, - "low": 950.55, - "close": 979.46, - "volume": 561861.0, - "amount": 5648563.0 - }, - { - "date": "2026-07-20", - "high": 1072.0, - "low": 950.55, - "close": 1004.0, - "volume": 453665.0, - "amount": 4609438.0 - } - ], - "601899": [ - { - "date": "2026-07-15", - "high": 29.34, - "low": 28.56, - "close": 28.83, - "volume": 2683491.0, - "amount": 777349.0 - }, - { - "date": "2026-07-16", - "high": 29.59, - "low": 28.56, - "close": 29.25, - "volume": 2654390.0, - "amount": 777340.0 - }, - { - "date": "2026-07-17", - "high": 29.59, - "low": 27.92, - "close": 28.36, - "volume": 2904169.0, - "amount": 824106.0 - }, - { - "date": "2026-07-19", - "high": 28.82, - "low": 27.92, - "close": 28.36, - "volume": 2904169.0, - "amount": 824106.0 - }, - { - "date": "2026-07-20", - "high": 29.45, - "low": 27.92, - "close": 29.35, - "volume": 2757683.0, - "amount": 799203.0 - } - ], - "688981": [ - { - "date": "2026-07-15", - "high": 162.78, - "low": 150.25, - "close": 153.64, - "volume": 83488259.0, - "amount": 1292438.0 - }, - { - "date": "2026-07-16", - "high": 162.78, - "low": 145.99, - "close": 151.8, - "volume": 84258615.0, - "amount": 1305529.0 - }, - { - "date": "2026-07-17", - "high": 160.47, - "low": 139.02, - "close": 139.88, - "volume": 102952043.0, - "amount": 1517166.0 - }, - { - "date": "2026-07-19", - "high": 155.51, - "low": 139.02, - "close": 139.88, - "volume": 102952043.0, - "amount": 1517166.0 - }, - { - "date": "2026-07-20", - "high": 155.51, - "low": 138.11, - "close": 144.0, - "volume": 93942500.0, - "amount": 1346494.0 - }, - { - "date": "2026-07-21", - "high": 156.72, - "low": 140.58, - "close": 155.81, - "volume": 74187978.0, - "amount": 1099957.0 - } - ], - "688372": [ - { - "date": "2026-07-15", - "high": 171.0, - "low": 145.0, - "close": 148.08, - "volume": 14474477.0, - "amount": 221152.0 - }, - { - "date": "2026-07-16", - "high": 171.0, - "low": 136.8, - "close": 138.19, - "volume": 11260179.0, - "amount": 160759.0 - }, - { - "date": "2026-07-17", - "high": 149.49, - "low": 120.66, - "close": 120.73, - "volume": 11689864.0, - "amount": 151702.0 - }, - { - "date": "2026-07-19", - "high": 139.2, - "low": 120.66, - "close": 120.73, - "volume": 11689864.0, - "amount": 151702.0 - }, - { - "date": "2026-07-20", - "high": 139.2, - "low": 115.0, - "close": 120.5, - "volume": 13508171.0, - "amount": 166596.0 - } - ], - "688411": [ - { - "date": "2026-07-15", - "high": 213.5, - "low": 203.2, - "close": 205.5, - "volume": 3016711.0, - "amount": 63128.0 - }, - { - "date": "2026-07-16", - "high": 213.5, - "low": 192.58, - "close": 193.9, - "volume": 3499172.0, - "amount": 69253.0 - }, - { - "date": "2026-07-17", - "high": 205.0, - "low": 179.03, - "close": 181.68, - "volume": 4238973.0, - "amount": 78494.0 - }, - { - "date": "2026-07-19", - "high": 193.48, - "low": 179.03, - "close": 181.68, - "volume": 4238973.0, - "amount": 78494.0 - }, - { - "date": "2026-07-20", - "high": 193.48, - "low": 175.6, - "close": 181.35, - "volume": 4399767.0, - "amount": 80465.0 - } - ], - "688271": [ - { - "date": "2026-07-15", - "high": 112.99, - "low": 108.3, - "close": 109.0, - "volume": 10561228.0, - "amount": 117122.0 - }, - { - "date": "2026-07-16", - "high": 112.99, - "low": 107.96, - "close": 111.72, - "volume": 8726471.0, - "amount": 96431.0 - }, - { - "date": "2026-07-17", - "high": 113.43, - "low": 107.96, - "close": 110.37, - "volume": 8809320.0, - "amount": 97913.0 - }, - { - "date": "2026-07-19", - "high": 113.43, - "low": 109.86, - "close": 110.37, - "volume": 8809320.0, - "amount": 97913.0 - }, - { - "date": "2026-07-20", - "high": 119.85, - "low": 107.89, - "close": 118.0, - "volume": 13911975.0, - "amount": 158683.0 - } - ], - "688439": [ - { - "date": "2026-07-15", - "high": 42.6, - "low": 41.61, - "close": 42.0, - "volume": 2121336.0, - "amount": 8928.0 - }, - { - "date": "2026-07-16", - "high": 42.6, - "low": 41.55, - "close": 42.0, - "volume": 1721672.0, - "amount": 7235.0 - }, - { - "date": "2026-07-17", - "high": 42.47, - "low": 39.58, - "close": 39.58, - "volume": 3189314.0, - "amount": 13157.0 - }, - { - "date": "2026-07-19", - "high": 42.38, - "low": 39.58, - "close": 39.58, - "volume": 3189314.0, - "amount": 13157.0 - }, - { - "date": "2026-07-20", - "high": 42.38, - "low": 37.05, - "close": 37.89, - "volume": 3734574.0, - "amount": 14394.0 - } - ], - "688588": [ - { - "date": "2026-07-15", - "high": 9.03, - "low": 8.62, - "close": 8.92, - "volume": 3291396.0, - "amount": 2935.0 - }, - { - "date": "2026-07-16", - "high": 9.23, - "low": 8.62, - "close": 9.02, - "volume": 3881104.0, - "amount": 3525.0 - }, - { - "date": "2026-07-17", - "high": 9.23, - "low": 8.55, - "close": 8.6, - "volume": 4173682.0, - "amount": 3684.0 - }, - { - "date": "2026-07-19", - "high": 9.19, - "low": 8.55, - "close": 8.6, - "volume": 4173682.0, - "amount": 3684.0 - }, - { - "date": "2026-07-20", - "high": 9.19, - "low": 8.46, - "close": 8.63, - "volume": 4281284.0, - "amount": 3721.0 - }, - { - "date": "2026-07-21", - "high": 8.77, - "low": 8.42, - "close": 8.71, - "volume": 3240110.0, - "amount": 2786.0 - } - ], - "688621": [ - { - "date": "2026-07-15", - "high": 59.66, - "low": 48.99, - "close": 58.0, - "volume": 11096865.0, - "amount": 63094.0 - }, - { - "date": "2026-07-16", - "high": 61.68, - "low": 48.99, - "close": 60.07, - "volume": 9202013.0, - "amount": 54187.0 - }, - { - "date": "2026-07-17", - "high": 61.75, - "low": 55.9, - "close": 57.58, - "volume": 6154202.0, - "amount": 36271.0 - }, - { - "date": "2026-07-19", - "high": 61.75, - "low": 56.73, - "close": 57.58, - "volume": 6154202.0, - "amount": 36271.0 - }, - { - "date": "2026-07-20", - "high": 61.75, - "low": 54.72, - "close": 56.88, - "volume": 4638705.0, - "amount": 26217.0 - }, - { - "date": "2026-07-21", - "high": 57.07, - "low": 53.55, - "close": 54.13, - "volume": 2827015.0, - "amount": 15448.0 - } - ], - "000850": [ - { - "date": "2026-07-15", - "high": 3.98, - "low": 3.83, - "close": 3.95, - "volume": 67251.0, - "amount": 2647.0 - }, - { - "date": "2026-07-17", - "high": 4.24, - "low": 3.98, - "close": 4.08, - "volume": 159057.0, - "amount": 6535.0 - }, - { - "date": "2026-07-19", - "high": 4.24, - "low": 3.98, - "close": 4.08, - "volume": 159057.0, - "amount": 6535.0 - }, - { - "date": "2026-07-20", - "high": 4.24, - "low": 3.94, - "close": 3.98, - "volume": 110497.0, - "amount": 4439.0 - } - ], - "301308": [ - { - "date": "2026-07-15", - "high": 557.0, - "low": 485.0, - "close": 488.0, - "volume": 227906.0, - "amount": 1170376.0 - }, - { - "date": "2026-07-17", - "high": 459.89, - "low": 395.37, - "close": 396.0, - "volume": 227898.0, - "amount": 954196.0 - } - ], - "001309": [ - { - "date": "2026-07-16", - "high": 596.16, - "low": 596.16, - "close": 596.16, - "volume": 1996.0, - "amount": 11899.0 - }, - { - "date": "2026-07-20", - "high": 500.0, - "low": 482.89, - "close": 482.89, - "volume": 177602.0, - "amount": 859692.0 - } - ], - "601318": [ - { - "date": "2026-07-16", - "high": 51.29, - "low": 50.61, - "close": 51.02, - "volume": 66142.0, - "amount": 33730.0 - } - ], - "688802": [ - { - "date": "2026-07-16", - "high": 848.86, - "low": 828.0, - "close": 837.66, - "volume": 155711.0, - "amount": 13011.0 - } - ], - "688630": [ - { - "date": "2026-07-16", - "high": 428.93, - "low": 377.81, - "close": 384.0, - "volume": 8621342.0, - "amount": 347099.0 - }, - { - "date": "2026-07-17", - "high": 394.01, - "low": 360.03, - "close": 372.37, - "volume": 7538280.0, - "amount": 284029.0 - } - ], - "000518": [ - { - "date": "2026-07-17", - "high": 3.87, - "low": 3.66, - "close": 3.81, - "volume": 585189.0, - "amount": 21986.0 - } - ], - "603885": [ - { - "date": "2026-07-17", - "high": 10.58, - "low": 10.3, - "close": 10.3, - "volume": 245805.0, - "amount": 25674.0 - }, - { - "date": "2026-07-19", - "high": 10.58, - "low": 10.3, - "close": 10.3, - "volume": 245805.0, - "amount": 25674.0 - }, - { - "date": "2026-07-20", - "high": 10.58, - "low": 10.15, - "close": 10.35, - "volume": 193759.0, - "amount": 19951.0 - } - ], - "688087": [ - { - "date": "2026-07-17", - "high": 38.23, - "low": 35.99, - "close": 36.18, - "volume": 2780918.0, - "amount": 10256.0 - }, - { - "date": "2026-07-19", - "high": 38.23, - "low": 35.99, - "close": 36.18, - "volume": 2780918.0, - "amount": 10256.0 - }, - { - "date": "2026-07-20", - "high": 38.97, - "low": 35.99, - "close": 38.57, - "volume": 2483595.0, - "amount": 9341.0 - } - ], - "688466": [ - { - "date": "2026-07-17", - "high": 13.19, - "low": 12.44, - "close": 12.6, - "volume": 1788822.0, - "amount": 2286.0 - }, - { - "date": "2026-07-19", - "high": 13.19, - "low": 12.44, - "close": 12.6, - "volume": 1788822.0, - "amount": 2286.0 - }, - { - "date": "2026-07-20", - "high": 13.19, - "low": 11.94, - "close": 12.28, - "volume": 1944699.0, - "amount": 2412.0 - } - ], - "600111": [ - { - "date": "2026-07-17", - "high": 38.79, - "low": 37.17, - "close": 37.45, - "volume": 665342.0, - "amount": 252376.0 - } - ], - "688041": [ - { - "date": "2026-07-17", - "high": 323.62, - "low": 298.0, - "close": 304.88, - "volume": 35790245.0, - "amount": 1105458.0 - } - ], - "688425": [ - { - "date": "2026-07-20", - "high": 4.15, - "low": 4.08, - "close": 4.14, - "volume": 1496345.0, - "amount": 618.0 - } - ], - "688608": [ - { - "date": "2026-07-20", - "high": 115.2, - "low": 110.0, - "close": 114.41, - "volume": 1143940.0, - "amount": 12834.0 - }, - { - "date": "2026-07-21", - "high": 126.0, - "low": 118.94, - "close": 124.29, - "volume": 6616802.0, - "amount": 81734.0 - } - ], - "688800": [ - { - "date": "2026-07-20", - "high": 65.11, - "low": 62.65, - "close": 63.51, - "volume": 1447347.0, - "amount": 9241.0 - }, - { - "date": "2026-07-21", - "high": 58.73, - "low": 50.0, - "close": 58.61, - "volume": 13309393.0, - "amount": 72395.0 - } - ], - "688758": [ - { - "date": "2026-07-20", - "high": 25.26, - "low": 22.95, - "close": 24.79, - "volume": 3826638.0, - "amount": 9338.0 - }, - { - "date": "2026-07-21", - "high": 25.18, - "low": 22.61, - "close": 25.15, - "volume": 12136498.0, - "amount": 29182.0 - } - ], - "688289": [ - { - "date": "2026-07-20", - "high": 15.64, - "low": 15.35, - "close": 15.52, - "volume": 755498.0, - "amount": 1172.0 - } - ], - "688726": [ - { - "date": "2026-07-20", - "high": 39.6, - "low": 38.03, - "close": 38.48, - "volume": 1020332.0, - "amount": 3950.0 - }, - { - "date": "2026-07-21", - "high": 37.72, - "low": 34.81, - "close": 37.68, - "volume": 6324151.0, - "amount": 23002.0 - } - ], - "688576": [ - { - "date": "2026-07-20", - "high": 39.29, - "low": 38.18, - "close": 38.67, - "volume": 61912.0, - "amount": 239.0 - }, - { - "date": "2026-07-21", - "high": 36.99, - "low": 34.83, - "close": 36.5, - "volume": 527607.0, - "amount": 1891.0 - } - ], - "688122": [ - { - "date": "2026-07-20", - "high": 49.28, - "low": 48.3, - "close": 48.95, - "volume": 1345698.0, - "amount": 6582.0 - } - ], - "605090": [ - { - "date": "2026-07-20", - "high": 39.6, - "low": 37.7, - "close": 38.19, - "volume": 87773.0, - "amount": 33970.0 - } - ], - "603766": [ - { - "date": "2026-07-20", - "high": 13.15, - "low": 12.91, - "close": 13.01, - "volume": 26823.0, - "amount": 3485.0 - } - ], - "688550": [ - { - "date": "2026-07-20", - "high": 44.8, - "low": 43.0, - "close": 44.58, - "volume": 977623.0, - "amount": 4270.0 - }, - { - "date": "2026-07-21", - "high": 42.53, - "low": 38.2, - "close": 42.38, - "volume": 4671790.0, - "amount": 18899.0 - } - ], - "688281": [ - { - "date": "2026-07-20", - "high": 44.4, - "low": 43.0, - "close": 43.01, - "volume": 473467.0, - "amount": 2067.0 - } - ], - "688617": [ - { - "date": "2026-07-20", - "high": 224.9, - "low": 201.31, - "close": 220.22, - "volume": 2634862.0, - "amount": 55058.0 - }, - { - "date": "2026-07-21", - "high": 223.66, - "low": 211.68, - "close": 211.84, - "volume": 1386950.0, - "amount": 30036.0 - } - ], - "688606": [ - { - "date": "2026-07-20", - "high": 45.44, - "low": 43.62, - "close": 44.26, - "volume": 544130.0, - "amount": 2421.0 - }, - { - "date": "2026-07-21", - "high": 44.26, - "low": 42.56, - "close": 43.17, - "volume": 433254.0, - "amount": 1870.0 - } - ], - "688314": [ - { - "date": "2026-07-20", - "high": 35.91, - "low": 30.24, - "close": 31.14, - "volume": 2832553.0, - "amount": 9286.0 - } - ], - "000711": [ - { - "date": "2026-07-20", - "high": 4.55, - "low": 4.21, - "close": 4.32, - "volume": 728146.0, - "amount": 31883.0 - } - ], - "688526": [ - { - "date": "2026-07-21", - "high": 12.87, - "low": 12.64, - "close": 12.78, - "volume": 1019907.0, - "amount": 1297.0 - } - ], - "688539": [ - { - "date": "2026-07-21", - "high": 23.58, - "low": 21.36, - "close": 23.58, - "volume": 2668816.0, - "amount": 5996.0 - } - ], - "688543": [ - { - "date": "2026-07-21", - "high": 35.18, - "low": 33.88, - "close": 34.96, - "volume": 4196332.0, - "amount": 14505.0 - } - ], - "688558": [ - { - "date": "2026-07-21", - "high": 25.99, - "low": 23.85, - "close": 25.93, - "volume": 1795891.0, - "amount": 4472.0 - } - ], - "688569": [ - { - "date": "2026-07-21", - "high": 16.4, - "low": 15.94, - "close": 16.15, - "volume": 708010.0, - "amount": 1141.0 - } - ], - "688580": [ - { - "date": "2026-07-21", - "high": 50.26, - "low": 46.18, - "close": 49.36, - "volume": 1555242.0, - "amount": 7462.0 - } - ], - "688581": [ - { - "date": "2026-07-21", - "high": 51.4, - "low": 49.7, - "close": 50.4, - "volume": 408774.0, - "amount": 2061.0 - } - ], - "688605": [ - { - "date": "2026-07-21", - "high": 71.87, - "low": 62.0, - "close": 71.59, - "volume": 7382675.0, - "amount": 49852.0 - } - ], - "688612": [ - { - "date": "2026-07-21", - "high": 28.89, - "low": 26.12, - "close": 28.79, - "volume": 4235793.0, - "amount": 11663.0 - } - ], - "688616": [ - { - "date": "2026-07-21", - "high": 9.73, - "low": 9.1, - "close": 9.54, - "volume": 1902612.0, - "amount": 1789.0 - } - ], - "688618": [ - { - "date": "2026-07-21", - "high": 24.2, - "low": 21.2, - "close": 24.09, - "volume": 3172718.0, - "amount": 7112.0 - } - ], - "688623": [ - { - "date": "2026-07-21", - "high": 55.55, - "low": 53.06, - "close": 54.3, - "volume": 617251.0, - "amount": 3342.0 - } - ], - "688626": [ - { - "date": "2026-07-21", - "high": 43.95, - "low": 40.4, - "close": 42.68, - "volume": 2132067.0, - "amount": 8910.0 - } - ], - "688648": [ - { - "date": "2026-07-21", - "high": 28.58, - "low": 26.66, - "close": 28.36, - "volume": 1502324.0, - "amount": 4155.0 - } - ], - "688678": [ - { - "date": "2026-07-21", - "high": 16.68, - "low": 14.81, - "close": 16.29, - "volume": 15515578.0, - "amount": 24554.0 - } - ], - "688683": [ - { - "date": "2026-07-21", - "high": 25.5, - "low": 22.37, - "close": 25.42, - "volume": 2193071.0, - "amount": 5211.0 - } - ], - "688689": [ - { - "date": "2026-07-21", - "high": 38.46, - "low": 32.27, - "close": 37.7, - "volume": 10503245.0, - "amount": 37306.0 - } - ], - "688718": [ - { - "date": "2026-07-21", - "high": 11.6, - "low": 10.31, - "close": 11.28, - "volume": 2949413.0, - "amount": 3222.0 - } - ], - "688799": [ - { - "date": "2026-07-21", - "high": 47.49, - "low": 43.8, - "close": 46.09, - "volume": 3286201.0, - "amount": 14940.0 - } - ], - "688805": [ - { - "date": "2026-07-21", - "high": 37.21, - "low": 33.51, - "close": 36.27, - "volume": 1330043.0, - "amount": 4655.0 - } - ], - "688816": [ - { - "date": "2026-07-21", - "high": 46.87, - "low": 44.03, - "close": 45.92, - "volume": 330420.0, - "amount": 1495.0 - } - ], - "688819": [ - { - "date": "2026-07-21", - "high": 22.19, - "low": 21.02, - "close": 21.72, - "volume": 3491209.0, - "amount": 7610.0 - } - ], - "688267": [ - { - "date": "2026-07-21", - "high": 16.48, - "low": 15.58, - "close": 16.35, - "volume": 1547669.0, - "amount": 2478.0 - } - ], - "688318": [ - { - "date": "2026-07-21", - "high": 71.5, - "low": 68.33, - "close": 69.5, - "volume": 3873944.0, - "amount": 27085.0 - } - ], - "688076": [ - { - "date": "2026-07-21", - "high": 27.79, - "low": 26.69, - "close": 27.18, - "volume": 2094599.0, - "amount": 5667.0 - } - ], - "688305": [ - { - "date": "2026-07-21", - "high": 53.5, - "low": 50.65, - "close": 53.47, - "volume": 2331843.0, - "amount": 12172.0 - } - ], - "688315": [ - { - "date": "2026-07-21", - "high": 12.86, - "low": 12.19, - "close": 12.57, - "volume": 3031391.0, - "amount": 3780.0 - } - ], - "688330": [ - { - "date": "2026-07-21", - "high": 31.78, - "low": 30.71, - "close": 31.25, - "volume": 753646.0, - "amount": 2345.0 - } - ], - "688331": [ - { - "date": "2026-07-21", - "high": 124.97, - "low": 118.01, - "close": 124.86, - "volume": 5979187.0, - "amount": 72466.0 - } - ], - "688336": [ - { - "date": "2026-07-21", - "high": 43.88, - "low": 40.6, - "close": 42.85, - "volume": 12339535.0, - "amount": 51873.0 - } - ], - "688410": [ - { - "date": "2026-07-21", - "high": 10.34, - "low": 9.71, - "close": 10.13, - "volume": 6328842.0, - "amount": 6336.0 - } - ], - "688455": [ - { - "date": "2026-07-21", - "high": 13.38, - "low": 11.97, - "close": 13.1, - "volume": 2149855.0, - "amount": 2744.0 - } - ], - "688578": [ - { - "date": "2026-07-21", - "high": 128.5, - "low": 122.8, - "close": 126.05, - "volume": 8949608.0, - "amount": 112505.0 - } - ] -} \ No newline at end of file diff --git a/deploy/profile-scripts/batch_reassess.py b/deploy/profile-scripts/batch_reassess.py index 196dab1b..5a464459 100644 --- a/deploy/profile-scripts/batch_reassess.py +++ b/deploy/profile-scripts/batch_reassess.py @@ -1,19 +1,30 @@ #!/usr/bin/env python3 -"""batch_reassess.py — 批量补全九维分析(逐只处理,间隔防限流) +"""batch_reassess.py — 批量补全12维(九维矩阵)LLM分析(逐只处理,间隔防限流) -用法: python3 batch_reassess.py [--all] [--code XXXXXX] +用法: + python3 batch_reassess.py # 所有缺分析/过期的 active 策略 + python3 batch_reassess.py --type holding # 只处理持仓策略 + python3 batch_reassess.py --type watchlist # 只处理自选策略 + python3 batch_reassess.py --type holding --today # 持仓每日刷新(今早未评过的强制重评) + python3 batch_reassess.py --code XXXXXX # 单只 -流程:收集最新数据 → 调LLM(gateway)写九维分析+策略 → 保存到DB +流程:收集最新数据 → 调LLM(gateway)写12维分析+策略 → 保存到DB """ -import sys, json, subprocess, sqlite3, re, time +import sys, json, subprocess, sqlite3, re, time, os from datetime import datetime +# ── 共享 LLM 客户端 + DB 工具(profile-scripts 硬链到同目录)── +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) +sys.path.insert(0, "/home/hmo/MoFin") +from llm_client import call_llm, REASSESS_MODEL, gateway_alive, ocg_alive +from mofin_db import snapshot_strategy_history + DB = "/home/hmo/MoFin/data/mofin.db" -GATEWAY = "http://127.0.0.1:8643/v1/chat/completions" COOLDOWN_HOURS = 1 +STALE_HOURS = 20 # 分析超过20小时视为过期,需要重评 def has_llm_analysis(code): - """检查是否为LLM生成的九维分析(>500字)""" + """检查是否为LLM生成的12维分析(>500字)""" conn = sqlite3.connect(DB) r = conn.execute("SELECT LENGTH(full_analysis) FROM holding_strategies WHERE code=? AND status='active'", (code,)).fetchone() conn.close() @@ -33,13 +44,41 @@ def in_cooldown(code): except: return False +def analysis_stale(code, force_today=False): + """分析是否过期(>STALE_HOURS 或 force_today 时今早4点前未重评)""" + conn = sqlite3.connect(DB) + r = conn.execute("SELECT reassessed_at FROM holding_strategies WHERE code=? AND status='active'", (code,)).fetchone() + conn.close() + if not r or not r[0]: + return True + try: + last = datetime.fromisoformat(r[0]) + if force_today: + today4am = datetime.now().replace(hour=4, minute=0, second=0, microsecond=0) + return last < today4am + return (datetime.now() - last).total_seconds() / 3600 > STALE_HOURS + except: + return True + +def get_portfolio(): + """从 portfolio_summary 读实时现金/总资产(不再硬编码)""" + try: + conn = sqlite3.connect(DB) + r = conn.execute("SELECT cash, total_assets FROM portfolio_summary WHERE id=1").fetchone() + conn.close() + if r and r[1]: + return int(r[0] or 0), int(r[1]) + except Exception: + pass + return 0, 0 + def collect_data(code): - """收集最新数据""" + """收集最新数据(含完整策略原文)""" data = {"code": code} - # 从DB读策略 + # 从DB读策略(含 full_analysis / changelog_json / position_advice) conn = sqlite3.connect(DB) - r = conn.execute("SELECT name, entry_low, entry_high, stop_loss, take_profit, timing_signal, action, rr_ratio, tech_snapshot, sector_context, stock_category FROM holding_strategies WHERE code=? AND status='active'", (code,)).fetchone() + r = conn.execute("SELECT name, entry_low, entry_high, stop_loss, take_profit, timing_signal, action, rr_ratio, tech_snapshot, sector_context, stock_category, full_analysis, changelog_json, reassessed_at, position_advice FROM holding_strategies WHERE code=? AND status='active'", (code,)).fetchone() if r: data["name"] = r[0] data["entry_low"] = r[1] or 0 @@ -52,10 +91,21 @@ def collect_data(code): data["tech_snapshot"] = r[8] or "" data["sector_context"] = r[9] or "" data["stock_category"] = r[10] or "" + data["full_analysis"] = r[11] or "" + data["changelog_json"] = r[12] or "" + data["reassessed_at"] = r[13] or "" + data["position_advice"] = r[14] or "" conn.close() # 从腾讯API拉最新价和基本面 - prefix = "sh" if str(code).startswith(("6","9")) else "sz" + # 代码前缀:5位=港股(hk),6/9开头=沪(sh),其他=深(sz) + _c = str(code) + if len(_c) == 5: + prefix = "hk" + elif _c.startswith(("6", "9")): + prefix = "sh" + else: + prefix = "sz" try: r = subprocess.run(["curl", "-s", f"http://qt.gtimg.cn/q={prefix}{code}"], capture_output=True, timeout=10) parts = r.stdout.decode("gbk", errors="ignore").split("~") @@ -80,9 +130,10 @@ def collect_data(code): return data def build_prompt(data): - """构建LLM prompt,要求输出完整策略""" - cash = 321271 # 可用现金(从DB读取) - total = 952879 # 总资产 + """构建LLM prompt,先审阅原策略再结合实时数据输出修改判断+九维矩阵分析""" + cash, total = get_portfolio() + if not total: + cash, total = 241330, 929727 # 兜底(DB读不到时) # 拉取资金流数据 _flow_note = "暂无资金流数据" @@ -122,7 +173,53 @@ def build_prompt(data): except: pass - return f"""你是一个资深A股分析师。请对{data['code']} {data.get('name','')}做一个完整的九维矩阵分析,并输出策略参数。 + # ── 构建【原策略全文】section ── + _params_parts = [] + if data.get('action'): _params_parts.append(f"当前策略: {data['action']}") + if data.get('timing_signal'): _params_parts.append(f"信号: {data['timing_signal']}") + if data.get('entry_low') or data.get('entry_high'): + _params_parts.append(f"买入区间: {data.get('entry_low',0)}~{data.get('entry_high',0)}") + if data.get('stop_loss'): _params_parts.append(f"止损: {data['stop_loss']}") + if data.get('take_profit'): _params_parts.append(f"止盈: {data['take_profit']}") + if data.get('position_advice'): _params_parts.append(f"仓位: {data['position_advice']}") + _params_str = " | ".join(_params_parts) if _params_parts else "无策略参数" + + # 最近3条变更记录 + _changelog_str = "无变更记录" + try: + _cl_raw = data.get('changelog_json', '') + if _cl_raw: + _cl = json.loads(_cl_raw) if isinstance(_cl_raw, str) else _cl_raw + if isinstance(_cl, list) and _cl: + _recent = _cl[-3:] if len(_cl) > 3 else _cl + _cl_lines = [] + for i, c in enumerate(_recent): + _act = c.get('action', c.get('reason', '')) if isinstance(c, dict) else str(c) + _ts = c.get('timestamp', '') if isinstance(c, dict) else '' + _cl_lines.append(f" {i+1}. {_ts[:16]} {_act[:80]}") + if _cl_lines: + _changelog_str = "\n".join(_cl_lines) + except: + pass + + # 完整分析原文(不截断) + _full_analysis = data.get('full_analysis', '') or '' + _fa_display = _full_analysis if _full_analysis else '(首次分析,无历史)' + + _orig_strategy_section = f"""当前策略参数: {_params_str} + +变更记录(最近3条): +{_changelog_str} + +完整分析原文: +{_fa_display}""" + + return f"""你是一个资深A股分析师。请先审阅以下【原策略全文】,判断是否需要修改策略,然后做出完整的九维矩阵分析。 + +【原策略全文】 +{_orig_strategy_section} + +── 以上是已有的策略,以下是当前实时数据,请结合两者做出判断 ── ⚠️ 重要:以下9个维度不是独立分析的,你必须交叉对比后给出综合结论。 例如:如果消息面利好但资金流在流出,说明利好可能是出货;如果基本面强但技术面破位,说明估值可能还没到底。 @@ -136,11 +233,18 @@ PE={data.get('pe','?')}(最新财报) 市值={data.get('mcap','?')}亿 资金流:{_flow_note}(近5日累计) 消息面:{_news_note}(最近3条,自动标注抓取时间) 当前信号:{data.get('timing_signal','?')} 分类:{data.get('stock_category','?')} -原策略:{(data.get('action','') or '')[:200]} 我的总资产={total}元,可用现金={cash}元。 -请严格按以下格式输出: +请严格按以下格式输出(注意节标题不可省略): + +【维持或修改】明确二选一判断:维持原策略 / 需要修改策略 +【修改点及理由】 +如果维持原策略 → 写"无需修改" +如果需要修改 → 逐条列出(每条格式:"- 修改点名称:理由说明") +【最终新策略】 +用自然语言输出完整的最终策略全文(200-400字),自包含核心交易逻辑、买入区间价格、止损价、止盈价、仓位比例、风险提示。 +⚠️ 本段不要使用【综合结论】【买入区间】等标签——用自然语言描述即可。 【交叉分析】用2-3句话说明哪些维度出现矛盾/共振,最关键的信号是什么 ① 大盘×基本面 [一句话,说明矛盾关系] @@ -162,13 +266,18 @@ PE={data.get('pe','?')}(最新财报) 市值={data.get('mcap','?')}亿 【建议止损】数字 【建议止盈】数字 -【建议仓位】只有综合结论为"买入"时才输出此项。仓位计算公式: +【建议仓位】⚠️不可省略。综合结论非"买入"时写"不新建仓";为"买入"时按以下公式: 基础仓位按RR确定:RR<1.5→不推荐,RR1.5~3→8%,RR3~5→12%,RR5+→15% 大盘偏弱×0.8,大盘偏强×1.15 蓝筹/白马×1.2,成长×0.85,题材/短线×0.6 最终仓位范围:5%~20% 同时考虑:现金{cash}元足够买多少手。 -输出格式:"X%(理由:一句话说明为什么这个仓位)""" +输出格式:"X%(理由:一句话说明为什么这个仓位)" + +⚠️ 输出纪律(必须遵守): +1. 直接以【维持或修改】开头,禁止任何寒暄、开场白、分隔线 +2. 禁止输出 或任何 XML/JSON/代码块 +3. 所有【】节标题一个都不能少""" def parse_response(text): """从LLM回复中提取策略参数""" result = {"signal": "", "entry_low": 0, "entry_high": 0, "stop_loss": 0, "take_profit": 0, "position": ""} @@ -217,10 +326,13 @@ def parse_response(text): return result def save_result(code, full_text, parsed): - """保存LLM结果到DB""" + """保存LLM结果到DB(先快照再UPDATE)""" conn = sqlite3.connect(DB) now = datetime.now().isoformat() + # ── 修改前快照 ── + snapshot_strategy_history(conn, code, 'batch_12d') + updates = ["full_analysis=?", "reassessed_at=?"] params = [full_text, now] @@ -260,106 +372,111 @@ def save_result(code, full_text, parsed): _tp = parsed.get("take_profit", 0) _pos = parsed.get("position", "") _msg = f"📈 {_name}({code}) 价{_p}→12维分析生成买入信号!区间{_el}~{_eh} 损{_sl} 盈{_tp} 仓位{_pos}" - import urllib.request, json as _jj - _req = urllib.request.Request("http://127.0.0.1:5805/", - data=_jj.dumps({"body": _msg, "to": "hmo@yoin.fun", "type": "chat"}).encode(), - headers={"Content-Type": "application/json"}) - urllib.request.urlopen(_req, timeout=5) - print(f" 📨 XMPP推送成功: {_msg[:60]}") + from alert_helper import notify as _notify, ACTION as _ACT + _notify("买入信号", _msg, _ACT) + print(f" \U0001f4e8 XMPP推送成功: {_msg[:60]}") except Exception as _e: - print(f" ⚠️ XMPP推送失败: {_e}") + print(f" \u26a0\ufe0f XMPP推送失败: {_e}") conn.close() -def process_stock(code): +def process_stock(code, force_today=False): """处理单只股票""" print(f"\n{'='*50}") print(f"处理: {code}") print(f"{'='*50}") - if has_llm_analysis(code): - print(f" ⏭ 已有LLM九维分析,跳过") + if in_cooldown(code): + print(f" \u23ed 冷却期内,跳过") return False - if in_cooldown(code): - print(f" ⏭ 冷却期内,跳过") + # 有分析且未过期 \u2192 跳过(除非 force_today 且今早未评) + if has_llm_analysis(code) and not analysis_stale(code, force_today): + print(f" \u23ed 已有12维分析且未过期,跳过") return False print(f" 收集数据...", flush=True) data = collect_data(code) if not data.get("price"): - print(f" ⚠️ 无价格数据,跳过") + print(f" \u26a0\ufe0f 无价格数据,跳过") return False print(f" 调LLM生成九维分析...", flush=True) prompt = build_prompt(data) - try: - r = subprocess.run(["curl", "-s", "--max-time", "300", - "-H", "Content-Type: application/json", - "-H", "Authorization: Bearer hermes123", - "-d", json.dumps({"model":"deepseek-v4-flash","messages":[{"role":"user","content":prompt}],"max_tokens":2048}), - GATEWAY], capture_output=True, timeout=310) - - if r.returncode != 0: - print(f" ❌ curl失败: {r.stderr.decode()[:100]}") - return False - - resp = json.loads(r.stdout) - if "choices" not in resp: - print(f" ❌ API异常: {str(resp)[:200]}") - return False - - full_text = resp["choices"][0]["message"]["content"] - print(f" ✅ LLM返回({len(full_text)}字)", flush=True) - - parsed = parse_response(full_text) - print(f" 信号={parsed['signal']} 区间={parsed['entry_low']}~{parsed['entry_high']} 损={parsed['stop_loss']} 盈={parsed['take_profit']} 仓位={parsed['position']}") - - save_result(code, full_text, parsed) - print(f" ✅ 已保存到DB") - return True - - except subprocess.TimeoutExpired: - print(f" ❌ 超时") - return False - except Exception as e: - print(f" ❌ 错误: {e}") + # ── 使用共享 LLM 客户端(替代 curl subprocess)── + result = call_llm(prompt, model=REASSESS_MODEL, max_tokens=4096) + + if not result["ok"]: + print(f" \u274c LLM调用失败: {result.get('error','未知错误')}") return False + + full_text = result["content"] + print(f" \u2705 LLM返回({len(full_text)}字, {result['elapsed']:.1f}s, 尝试{result['attempts']}次)", flush=True) + + parsed = parse_response(full_text) + print(f" 信号={parsed['signal']} 区间={parsed['entry_low']}~{parsed['entry_high']} 损={parsed['stop_loss']} 盈={parsed['take_profit']} 仓位={parsed['position']}") + + save_result(code, full_text, parsed) + print(f" \u2705 已保存到DB") + return True def main(): + # ── 双通道预检:OCG直连 + hermes gateway 兜底,全挂才退出 ── + _ocg_ok = ocg_alive() + _gw_ok = gateway_alive() + if not _ocg_ok and not _gw_ok: + print("[FATAL] OCG上游与hermes gateway均不可用,退出") + sys.exit(1) + if not _ocg_ok: + print("[WARN] OCG直连不可用,将使用gateway兜底(agent运行时,较慢)") + if not _gw_ok: + print("[WARN] hermes gateway不可用,仅使用OCG直连") + codes = [] + force_today = "--today" in sys.argv + dtype = None + if "--type" in sys.argv: + idx = sys.argv.index("--type") + dtype = sys.argv[idx + 1] # holding | watchlist | all if "--code" in sys.argv: idx = sys.argv.index("--code") codes = [sys.argv[idx+1]] else: - # 所有自选策略 + # 按类型筛选 active 策略 + type_map = {"holding": "持仓策略", "watchlist": "自选策略"} conn = sqlite3.connect(DB) - rows = conn.execute("SELECT code FROM holding_strategies WHERE status='active' AND decision_type='自选策略' ORDER BY code").fetchall() + if dtype in type_map: + rows = conn.execute( + "SELECT code FROM holding_strategies WHERE status='active' AND decision_type=? ORDER BY code", + (type_map[dtype],)).fetchall() + else: + rows = conn.execute( + "SELECT code FROM holding_strategies WHERE status='active' ORDER BY decision_type, code").fetchall() conn.close() codes = [r[0] for r in rows] - print(f"待处理: {len(codes)}只") + print(f"待处理: {len(codes)}只 (type={dtype or 'all'}, force_today={force_today})") ok = 0 fail = 0 skip = 0 for i, code in enumerate(codes): - if has_llm_analysis(code): - print(f" [{i+1}/{len(codes)}] ⏭ {code} 已有LLM分析") + if has_llm_analysis(code) and not analysis_stale(code, force_today): + print(f" [{i+1}/{len(codes)}] \u23ed {code} 已有12维分析且未过期") skip += 1 continue print(f" [{i+1}/{len(codes)}] ", end="", flush=True) - if process_stock(code): + if process_stock(code, force_today): ok += 1 else: fail += 1 - # 间隔15秒(防gateway过载) + # 间隔8秒(pro model较重但gateway可承受;retry逻辑吸收瞬断) if i < len(codes) - 1: - print(f" 等待15秒...", flush=True) - time.sleep(15) + print(f" 等待8秒...", flush=True) + time.sleep(8) print(f"\n{'='*50}") print(f"完成: {ok}成功, {fail}失败, {skip}跳过") diff --git a/deploy/profile-scripts/candidate_filter.py b/deploy/profile-scripts/candidate_filter.py index e33ab5b3..4a48c068 100644 --- a/deploy/profile-scripts/candidate_filter.py +++ b/deploy/profile-scripts/candidate_filter.py @@ -17,7 +17,9 @@ DB_PATH = Path("/home/hmo/MoFin/data/mofin.db") UA = "Mozilla/5.0" def get_conn(): - return sqlite3.connect(str(DB_PATH)) + c = sqlite3.connect(str(DB_PATH), timeout=30) + c.execute("PRAGMA busy_timeout=30000") + return c def log_candidate(conn, code, stage, passed, detail): """记录过滤日志""" diff --git a/deploy/profile-scripts/data/market_scan_summary.json b/deploy/profile-scripts/data/market_scan_summary.json deleted file mode 100644 index f5373921..00000000 --- a/deploy/profile-scripts/data/market_scan_summary.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "timestamp": "2026-07-21 11:30", - "source": "ths", - "sector_count": 90, - "xiaoguo_status": "offline", - "note": "小果不在线,未做LLM全市场筛选" -} \ No newline at end of file diff --git a/deploy/profile-scripts/fix_gateway_port.py b/deploy/profile-scripts/fix_gateway_port.py index 2d7b0996..283cc1b7 100644 --- a/deploy/profile-scripts/fix_gateway_port.py +++ b/deploy/profile-scripts/fix_gateway_port.py @@ -21,33 +21,26 @@ def port_open(port, host="127.0.0.1"): s.close() def check_session_health(): - """调gateway API,检测session是否卡死。超过15s无响应→不健康""" + """检测 gateway LLM 是否可用——扫 agent.log 最近一次真实调用结果。 + 不再发真实 LLM ping(25s 超时对 20-100s 的冷启动延迟必误报,且每次白烧 22k token)。 + """ try: - payload = json.dumps({ - "model": "hermes-agent", - "messages": [{"role": "user", "content": "ping"}] - }).encode() - req = urllib.request.Request(GATEWAY_URL, data=payload, method="POST") - req.add_header("Content-Type", "application/json") - req.add_header("Authorization", f"Bearer {API_KEY}") - req.add_header("X-Hermes-Session-Id", SESSION_ID) - t0 = time.time() - with urllib.request.urlopen(req, timeout=25) as r: - data = json.loads(r.read()) - reply = data.get("choices", [{}])[0].get("message", {}).get("content", "") - elapsed = time.time() - t0 - if reply: - print(f"Session {SESSION_ID} 健康 ✓ ({elapsed:.1f}s)") - return True - else: - print(f"Session {SESSION_ID} 返回空", file=sys.stderr) - return False - except urllib.request.HTTPError as e: - print(f"Session {SESSION_ID} HTTP错误: {e.code}", file=sys.stderr) - return False + sys.path.insert(0, '/home/hmo/MoFin') + from xmpp_logger import _scan_agent_log + r = _scan_agent_log(time.time(), "zhiwei") + if r["status"] == "ok": + print(f"Session {SESSION_ID} 健康 ✓ (agent.log: latency={r.get('latency')}, {r.get('age_sec')}s前)") + return True + # error/unknown:只有近期有明确失败记录才判不健康 + if r["status"] == "error": + print(f"Session {SESSION_ID} 不健康: agent.log 最近调用失败 — {r.get('error','')[:100]}", file=sys.stderr) + return False + # unknown(无近期调用记录)= 空闲,不算不健康 + print(f"Session {SESSION_ID} 无近期调用记录(空闲正常)") + return True except Exception as e: - print(f"Session {SESSION_ID} 不健康: {e}", file=sys.stderr) - return False + print(f"Session {SESSION_ID} 健康检查异常: {e}(按健康处理)", file=sys.stderr) + return True def restart_gateway(): """通过systemd重启gateway""" diff --git a/deploy/profile-scripts/per_stock_reassess.py b/deploy/profile-scripts/per_stock_reassess.py index c5c1d172..f02b5be4 100644 --- a/deploy/profile-scripts/per_stock_reassess.py +++ b/deploy/profile-scripts/per_stock_reassess.py @@ -34,8 +34,11 @@ def _in_cooldown(code): sys.path.insert(0, "/home/hmo/web-dashboard") sys.path.insert(0, "/home/hmo/MoFin") +sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) # profile-scripts 硬链目录 from strategy_lifecycle import reassess_with_context as reassess_strategy from mo_data import read_decisions, read_portfolio +from llm_client import call_llm, REASSESS_MODEL +from mofin_db import snapshot_strategy_history def _build_full_analysis(code, entry, result): @@ -431,18 +434,76 @@ def main(): except: pass - _prompt = f"""你是一个资深股票分析师。请对股票{code}做一个完整的12维矩阵分析(3横×4纵:大盘/行业/个股 × 基本面/消息面/技术面/资金面)。 + # ── 拉取已有策略全文 + 最近变更 ── + _existing_full_analysis = "" + _existing_changelog_text = "无变更记录" + try: + _edb = __import__('sqlite3').connect("/home/hmo/MoFin/data/mofin.db") + _er = _edb.execute( + "SELECT full_analysis, changelog_json FROM holding_strategies " + "WHERE code=? AND status='active'", (code,) + ).fetchone() + if _er: + _existing_full_analysis = _er[0] or "" + _cl_raw = _er[1] or "" + if _cl_raw: + _cl = __import__('json').loads(_cl_raw) if isinstance(_cl_raw, str) else _cl_raw + if isinstance(_cl, list) and _cl: + _recent = _cl[-3:] + _existing_changelog_text = "\n".join( + [f" [{c.get('timestamp','?')}] {c.get('action','?')}: {c.get('reason','')}"[:120] + for c in reversed(_recent)] + ) + _edb.close() + except: + pass + + _prompt = f"""你是一个资深股票分析师。请对股票{code}评估现有策略是否仍然有效,并输出完整的新策略。 + +╔══════════════════════════════════════════════╗ +║ 📋 第一步:审阅原策略 ║ +╚══════════════════════════════════════════════╝ + +【原策略全文】(上次完整分析): +{_existing_full_analysis or '暂无完整策略分析'} + +【当前策略参数】: + 价格={price} 信号={result.get("timing_signal") or entry.get("timing_signal","")} + 买入区间={entry.get("entry_low",0)}~{entry.get("entry_high",0)} + 止损={entry.get("stop_loss",0)} 止盈={entry.get("take_profit",0)} + RR={result.get("rr_ratio", entry.get("rr_ratio", 0))} + 策略={result.get("action") or entry.get("action","")} + 行业={(result.get("sector_context") or entry.get("sector_context",""))[:50]}(当日实时) + 技术={(result.get("tech_snapshot") or entry.get("tech_snapshot",""))[:200]}(MA=5/10/20/60日 支撑阻力=近20日 量价=当日+近5日趋势) + +【最近变更记录】: +{_existing_changelog_text} + +╔══════════════════════════════════════════════╗ +║ 📊 第二步:12维矩阵交叉分析 ║ +╚══════════════════════════════════════════════╝ ⚠️ 重要:12个维度必须交叉对比,找出矛盾/共振点,给出综合判断。 -当前数据(实时API,每条标注时间窗口,禁止使用模型训练数据): -大盘={_macro_desc or "震荡"}(当日实时) | PE/市值={_pe_val} {_pb_val}(最新财报) | 价格={price} 区间={entry.get("entry_low",0)}~{entry.get("entry_high",0)} 止损={entry.get("stop_loss",0)} 止盈={entry.get("take_profit",0)} RR={result.get("rr_ratio",entry.get("rr_ratio",0))} | 信号={result.get("timing_signal") or entry.get("timing_signal","")} | 行业={(result.get("sector_context") or entry.get("sector_context",""))[:50]}(当日实时) -策略={(result.get("action") or entry.get("action",""))[:200]} -技术={(result.get("tech_snapshot") or entry.get("tech_snapshot",""))[:200]}(MA=5/10/20/60日 支撑阻力=近20日 量价=当日+近5日趋势) +当前实时数据(每条标注时间窗口,禁止使用模型训练数据): +大盘={_macro_desc or "震荡"}(当日实时) | PE/市值={_pe_val} {_pb_val}(最新财报) 资金流={_flow_note}(近5日累计) 消息面={_news_note}(最近3条,自动标注抓取时间) -格式: +╔══════════════════════════════════════════════╗ +║ 📝 第三步:决策输出 ║ +╚══════════════════════════════════════════════╝ + +请严格按以下顺序输出: + +【维持或修改】判断当前策略是否仍然有效,回答「维持」或「修改」。 + +【修改点及理由】(如果维持,写「无需修改」;如果修改,逐条列出): + - 修改什么参数/方向 + - 理由(引用具体维度矛盾或共振) + +【最终新策略】(完整策略全文,self-contained,可直接存入DB) + 【交叉分析】哪些维度矛盾/共振,关键信号 ① 大盘×基本面 ② 大盘×消息面 ③ 大盘×技术面 ④ 大盘×资金面 ⑤ 行业×基本面 ⑥ 行业×消息面 ⑦ 行业×技术面 ⑧ 行业×资金面 @@ -452,26 +513,42 @@ def main(): 【综合结论】(买入/关注/观望/卖出) 【操作建议】 【建议止损】 -【建议止盈】""" - try: - _ur = __import__('urllib.request', fromlist=['Request']) - _req = _ur.Request("http://127.0.0.1:8643/v1/chat/completions", - data=__import__('json').dumps({"model":"deepseek-v4-flash","messages":[{"role":"user","content":_prompt}],"max_tokens":1024}).encode(), - headers={"Content-Type":"application/json","Authorization":"Bearer hermes123"}) - _resp = _ur.build_opener(_ur.ProxyHandler({})).open(_req, timeout=300) - _llm_out = __import__('json').loads(_resp.read().decode())["choices"][0]["message"]["content"] - _full_analysis_text = _llm_out - print(f" ✅ LLM12维分析完成({len(_full_analysis_text)}字)", flush=True) - except Exception as _e: - print(f" ❌ LLM12维分析失败: {_e}", file=__import__('sys').stderr) - _full_analysis_text = None +【建议止盈】 +【建议仓位】⚠️不可省略,非"买入"时写"不新建仓" - # 保存到DB +⚠️ 输出纪律(必须遵守): +1. 直接以【维持或修改】开头,禁止任何寒暄、开场白、分隔线 +2. 禁止输出 或任何 XML/JSON/代码块 +3. 所有【】节标题一个都不能少""" + _full_analysis_text = None + try: + _llm_result = call_llm(_prompt, max_tokens=4096, timeout=150, retries=1, backoff=20) + if _llm_result["ok"]: + _full_analysis_text = _llm_result["content"] + print(f" ✅ LLM12维分析完成({len(_full_analysis_text)}字, {_llm_result['elapsed']:.1f}s)", flush=True) + else: + print(f" ❌ LLM12维分析失败({_llm_result['attempts']}次): {_llm_result['error'][:200]}", flush=True) + except Exception as _e: + print(f" ❌ LLM12维分析异常: {_e}", flush=True) + + # ── 保存到DB(覆写前先快照)── _fa_conn = __import__('sqlite3').connect("/home/hmo/MoFin/data/mofin.db") - _fa_conn.execute("UPDATE holding_strategies SET full_analysis=?, reassessed_at=? WHERE code=? AND status='active'", (_full_analysis_text, __import__('datetime').datetime.now().isoformat(), code)) - _fa_conn.commit() + if _full_analysis_text: + # 快照旧策略(使用共享函数) + try: + snapshot_strategy_history(_fa_conn, code, "per_stock_12d") + except Exception as _se: + print(f" ⚠️ 快照失败: {_se}", flush=True) + + _fa_conn.execute( + "UPDATE holding_strategies SET full_analysis=?, reassessed_at=? WHERE code=? AND status='active'", + (_full_analysis_text, __import__('datetime').datetime.now().isoformat(), code)) + _fa_conn.commit() _fa_conn.close() - print(f" ✅ 完整12维分析已保存({len(_full_analysis_text)}字)" if _full_analysis_text else f" ⚠️ 12维分析未完成,跳过保存") + if _full_analysis_text: + print(f" ✅ 完整12维分析已保存({len(_full_analysis_text)}字)") + else: + print(f" ⚠️ 12维分析未完成,跳过保存") print(f" [DB] holding_strategies 已更新: {code}") # 从LLM输出提取信号 if _full_analysis_text and '【综合结论】' in _full_analysis_text: @@ -490,10 +567,8 @@ def main(): "SELECT name, price, entry_low, entry_high, stop_loss, take_profit, position_advice FROM holding_strategies WHERE code=? AND status='active'", (code,)).fetchone() if _nr2: _xm = f"📈 {_nr2[0] or code}({code}) 价{_nr2[1]}→12维买入信号!区间{_nr2[2]}~{_nr2[3]} 损{_nr2[4]} 盈{_nr2[5]} 仓位{_nr2[6] or '-'}" - _xr = __import__('urllib.request').Request("http://127.0.0.1:5805/", - data=__import__('json').dumps({"body": _xm, "to": "hmo@yoin.fun", "type": "chat"}).encode(), - headers={"Content-Type": "application/json"}) - __import__('urllib.request').urlopen(_xr, timeout=5) + from alert_helper import notify as _notify2, ACTION as _ACT2 + _notify2("买入信号", _xm, _ACT2) print(f" 📨 XMPP推送买入信号") except: pass except: pass diff --git a/deploy/profile-scripts/stale_detector.py b/deploy/profile-scripts/stale_detector.py index 93412551..fc805b83 100644 --- a/deploy/profile-scripts/stale_detector.py +++ b/deploy/profile-scripts/stale_detector.py @@ -142,7 +142,7 @@ def main(): reassess_scripts.append(code) print(f"[AUTO_REASSESS] {name}({code}) 价{cur_price:.2f}偏离买入区中心{center:.2f} {drift:+.0f}% → 触发重评") if reassess_scripts: - # 调用 per_stock_reassess + # 调用 per_stock_reassess(每轮最多5只,防LLM慢导致整批超时;其余下轮继续) reassess_path = None for p in ['/home/hmo/MoFin/scripts/per_stock_reassess.py', '/home/hmo/.hermes/profiles/position-analyst/scripts/per_stock_reassess.py']: @@ -150,12 +150,20 @@ def main(): reassess_path = p break if reassess_path: - for code in reassess_scripts: - r = subprocess.run(['python3', reassess_path, code], - capture_output=True, text=True, timeout=60) - out = r.stdout.strip()[:200] if r.stdout else "" - err = r.stderr.strip()[:200] if r.stderr else "" - print(f" → {code}: exited={r.returncode} {out}") + MAX_PER_RUN = 5 + batch = reassess_scripts[:MAX_PER_RUN] + if len(reassess_scripts) > MAX_PER_RUN: + print(f"[AUTO_REASSESS] 本轮限{MAX_PER_RUN}只,剩余{len(reassess_scripts)-MAX_PER_RUN}只下轮继续") + for code in batch: + try: + # LLM 重评冷启动 20-100s,deepseek-v4-pro 更慢 → 480s + r = subprocess.run(['python3', reassess_path, code], + capture_output=True, text=True, timeout=480) + out = r.stdout.strip()[:200] if r.stdout else "" + err = r.stderr.strip()[:200] if r.stderr else "" + print(f" → {code}: exited={r.returncode} {out}") + except subprocess.TimeoutExpired: + print(f" → {code}: 超时480s(LLM仍慢),下轮重试") except Exception as e: print(f"[AUTO_REASSESS FAIL] {e}") # ----- 结束 自选股重评 -----