diff --git a/examples/data/XSHG_5min_600977.csv b/examples/data/XSHG_5min_600977.csv deleted file mode 100644 index 37ed89d..0000000 --- a/examples/data/XSHG_5min_600977.csv +++ /dev/null @@ -1,2501 +0,0 @@ -timestamps,open,high,low,close,volume,amount -2024-06-18 11:15:00,11.27,11.28,11.26,11.27,379.0,427161.0 -2024-06-18 11:20:00,11.27,11.28,11.27,11.27,277.0,312192.0 -2024-06-18 11:25:00,11.27,11.27,11.26,11.27,380.0,427954.0 -2024-06-18 11:30:00,11.26,11.27,11.26,11.27,761.0,856971.0 -2024-06-18 13:05:00,11.27,11.27,11.25,11.26,1439.0,1620733.0 -2024-06-18 13:10:00,11.26,11.26,11.25,11.25,529.0,595311.0 -2024-06-18 13:15:00,11.26,11.27,11.25,11.26,389.0,438017.0 -2024-06-18 13:20:00,11.26,11.32,11.26,11.32,4459.0,5037553.0 -2024-06-18 13:25:00,11.32,11.32,11.3,11.31,2551.0,2886053.0 -2024-06-18 13:30:00,11.31,11.33,11.3,11.32,1185.0,1340985.0 -2024-06-18 13:35:00,11.32,11.33,11.31,11.32,1296.0,1467314.0 -2024-06-18 13:40:00,11.33,11.33,11.3,11.3,1229.0,1390698.0 -2024-06-18 13:45:00,11.31,11.31,11.3,11.3,568.0,641846.0 -2024-06-18 13:50:00,11.3,11.32,11.3,11.31,1168.0,1321141.0 -2024-06-18 13:55:00,11.31,11.31,11.29,11.29,867.0,979738.0 -2024-06-18 14:00:00,11.3,11.3,11.28,11.29,1026.0,1158037.0 -2024-06-18 14:05:00,11.28,11.3,11.28,11.29,752.0,849034.0 -2024-06-18 14:10:00,11.29,11.3,11.28,11.29,284.0,320630.0 -2024-06-18 14:15:00,11.29,11.3,11.29,11.29,485.0,547861.0 -2024-06-18 14:20:00,11.29,11.3,11.29,11.29,246.0,277867.0 -2024-06-18 14:25:00,11.3,11.3,11.29,11.3,188.0,212415.0 -2024-06-18 14:30:00,11.29,11.31,11.29,11.3,469.0,529984.0 -2024-06-18 14:35:00,11.3,11.31,11.29,11.3,935.0,1057044.0 -2024-06-18 14:40:00,11.3,11.32,11.3,11.31,978.0,1106460.0 -2024-06-18 14:45:00,11.32,11.32,11.31,11.31,524.0,592817.0 -2024-06-18 14:50:00,11.32,11.33,11.31,11.31,1758.0,1990407.0 -2024-06-18 14:55:00,11.31,11.33,11.31,11.31,1173.0,1327496.0 -2024-06-18 15:00:00,11.31,11.32,11.31,11.32,2019.0,2284686.0 -2024-06-19 09:35:00,11.36,11.37,11.32,11.35,5606.0,6361534.0 -2024-06-19 09:40:00,11.35,11.35,11.3,11.3,1773.0,2006819.0 -2024-06-19 09:45:00,11.31,11.34,11.31,11.33,1108.0,1254369.0 -2024-06-19 09:50:00,11.34,11.35,11.31,11.33,1162.0,1316325.0 -2024-06-19 09:55:00,11.33,11.34,11.31,11.31,940.0,1064577.0 -2024-06-19 10:00:00,11.31,11.32,11.3,11.31,902.0,1019926.0 -2024-06-19 10:05:00,11.31,11.31,11.28,11.28,1996.0,2253586.0 -2024-06-19 10:10:00,11.28,11.3,11.27,11.28,1654.0,1865591.0 -2024-06-19 10:15:00,11.28,11.3,11.27,11.27,1256.0,1416821.0 -2024-06-19 10:20:00,11.27,11.28,11.26,11.26,1431.0,1612514.0 -2024-06-19 10:25:00,11.26,11.27,11.25,11.26,1885.0,2121914.0 -2024-06-19 10:30:00,11.26,11.27,11.25,11.25,631.0,710455.0 -2024-06-19 10:35:00,11.25,11.27,11.25,11.26,339.0,381780.0 -2024-06-19 10:40:00,11.26,11.27,11.26,11.26,659.0,742174.0 -2024-06-19 10:45:00,11.26,11.27,11.25,11.26,582.0,655187.0 -2024-06-19 10:50:00,11.27,11.27,11.25,11.26,846.0,952340.0 -2024-06-19 10:55:00,11.26,11.27,11.24,11.24,880.0,989908.0 -2024-06-19 11:00:00,11.24,11.25,11.23,11.25,1588.0,1784353.0 -2024-06-19 11:05:00,11.25,11.25,11.24,11.25,268.0,301270.0 -2024-06-19 11:10:00,11.24,11.25,11.23,11.23,803.0,902030.0 -2024-06-19 11:15:00,11.23,11.24,11.22,11.22,760.0,853730.0 -2024-06-19 11:20:00,11.23,11.23,11.22,11.23,579.0,649687.0 -2024-06-19 11:25:00,11.23,11.23,11.22,11.22,330.0,370407.0 -2024-06-19 11:30:00,11.22,11.24,11.22,11.22,439.0,492948.0 -2024-06-19 13:05:00,11.24,11.24,11.21,11.21,2163.0,2426493.0 -2024-06-19 13:10:00,11.22,11.23,11.21,11.21,1298.0,1455405.0 -2024-06-19 13:15:00,11.22,11.22,11.2,11.2,969.0,1085634.0 -2024-06-19 13:20:00,11.21,11.22,11.19,11.19,1506.0,1687003.0 -2024-06-19 13:25:00,11.2,11.2,11.18,11.2,780.0,872818.0 -2024-06-19 13:30:00,11.2,11.2,11.18,11.19,626.0,700545.0 -2024-06-19 13:35:00,11.2,11.22,11.19,11.21,584.0,654510.0 -2024-06-19 13:40:00,11.22,11.22,11.19,11.19,846.0,948063.0 -2024-06-19 13:45:00,11.2,11.2,11.19,11.19,1161.0,1299253.0 -2024-06-19 13:50:00,11.19,11.2,11.19,11.19,601.0,672581.0 -2024-06-19 13:55:00,11.19,11.21,11.19,11.2,608.0,680712.0 -2024-06-19 14:00:00,11.21,11.21,11.19,11.2,429.0,480088.0 -2024-06-19 14:05:00,11.2,11.21,11.19,11.19,483.0,541090.0 -2024-06-19 14:10:00,11.19,11.2,11.18,11.18,1202.0,1344822.0 -2024-06-19 14:15:00,11.18,11.19,11.18,11.19,1254.0,1402314.0 -2024-06-19 14:20:00,11.18,11.2,11.18,11.18,661.0,739534.0 -2024-06-19 14:25:00,11.18,11.19,11.17,11.17,749.0,837431.0 -2024-06-19 14:30:00,11.17,11.17,11.16,11.17,895.0,999475.0 -2024-06-19 14:35:00,11.17,11.18,11.16,11.18,979.0,1093029.0 -2024-06-19 14:40:00,11.17,11.18,11.17,11.18,371.0,414729.0 -2024-06-19 14:45:00,11.18,11.19,11.17,11.17,497.0,555470.0 -2024-06-19 14:50:00,11.18,11.19,11.17,11.18,1001.0,1118551.0 -2024-06-19 14:55:00,11.18,11.18,11.16,11.16,1411.0,1575333.0 -2024-06-19 15:00:00,11.16,11.19,11.16,11.16,2763.0,3086089.0 -2024-06-20 09:35:00,11.13,11.15,11.07,11.13,3450.0,3833838.0 -2024-06-20 09:40:00,11.13,11.15,11.13,11.14,1725.0,1920516.0 -2024-06-20 09:45:00,11.14,11.14,11.09,11.09,2419.0,2688742.0 -2024-06-20 09:50:00,11.09,11.11,11.07,11.08,2499.0,2771114.0 -2024-06-20 09:55:00,11.1,11.11,11.09,11.1,1985.0,2204227.0 -2024-06-20 10:00:00,11.11,11.11,11.08,11.08,661.0,733097.0 -2024-06-20 10:05:00,11.08,11.08,11.06,11.07,1747.0,1934268.0 -2024-06-20 10:10:00,11.08,11.1,11.08,11.1,1065.0,1180734.0 -2024-06-20 10:15:00,11.09,11.1,11.06,11.06,1017.0,1126598.0 -2024-06-20 10:20:00,11.07,11.08,11.04,11.06,3125.0,3457253.0 -2024-06-20 10:25:00,11.06,11.07,11.06,11.07,992.0,1097960.0 -2024-06-20 10:30:00,11.08,11.1,11.07,11.1,481.0,533086.0 -2024-06-20 10:35:00,11.09,11.1,11.08,11.09,320.0,354944.0 -2024-06-20 10:40:00,11.1,11.1,11.08,11.09,541.0,599728.0 -2024-06-20 10:45:00,11.09,11.09,11.08,11.09,251.0,278128.0 -2024-06-20 10:50:00,11.09,11.1,11.07,11.07,731.0,810352.0 -2024-06-20 10:55:00,11.08,11.08,11.05,11.05,1405.0,1554667.0 -2024-06-20 11:00:00,11.06,11.07,11.05,11.06,941.0,1040747.0 -2024-06-20 11:05:00,11.05,11.07,11.05,11.05,381.0,421282.0 -2024-06-20 11:10:00,11.06,11.06,11.04,11.05,781.0,862948.0 -2024-06-20 11:15:00,11.05,11.05,11.04,11.05,339.0,374531.0 -2024-06-20 11:20:00,11.06,11.06,11.02,11.03,2889.0,3187747.0 -2024-06-20 11:25:00,11.03,11.05,11.03,11.04,577.0,636955.0 -2024-06-20 11:30:00,11.04,11.05,11.02,11.03,1163.0,1282943.0 -2024-06-20 13:05:00,11.02,11.04,11.01,11.04,1011.0,1114505.0 -2024-06-20 13:10:00,11.04,11.04,11.0,11.01,1951.0,2149164.0 -2024-06-20 13:15:00,11.01,11.02,11.0,11.02,1587.0,1746325.0 -2024-06-20 13:20:00,11.02,11.02,11.0,11.0,833.0,916817.0 -2024-06-20 13:25:00,11.0,11.0,10.98,11.0,2833.0,3114174.0 -2024-06-20 13:30:00,10.99,10.99,10.97,10.99,2393.0,2627686.0 -2024-06-20 13:35:00,10.99,10.99,10.98,10.98,803.0,882552.0 -2024-06-20 13:40:00,10.98,11.0,10.98,11.0,1150.0,1263279.0 -2024-06-20 13:45:00,11.0,11.03,11.0,11.01,1019.0,1122062.0 -2024-06-20 13:50:00,11.02,11.03,11.0,11.03,710.0,782386.0 -2024-06-20 13:55:00,11.03,11.03,11.01,11.03,388.0,427694.0 -2024-06-20 14:00:00,11.01,11.02,11.01,11.02,100.0,110378.0 -2024-06-20 14:05:00,11.03,11.05,11.02,11.02,1151.0,1269851.0 -2024-06-20 14:10:00,11.03,11.03,11.0,11.01,840.0,925112.0 -2024-06-20 14:15:00,11.01,11.01,11.0,11.0,648.0,712856.0 -2024-06-20 14:20:00,11.0,11.01,10.99,11.0,691.0,760290.0 -2024-06-20 14:25:00,11.0,11.01,11.0,11.01,587.0,645966.0 -2024-06-20 14:30:00,11.01,11.02,11.0,11.01,659.0,725653.0 -2024-06-20 14:35:00,11.02,11.02,10.99,10.99,946.0,1040515.0 -2024-06-20 14:40:00,10.99,11.02,10.99,11.01,1963.0,2159046.0 -2024-06-20 14:45:00,10.99,11.01,10.99,11.01,626.0,688232.0 -2024-06-20 14:50:00,11.01,11.02,11.0,11.01,523.0,575829.0 -2024-06-20 14:55:00,11.01,11.02,11.0,11.01,637.0,701307.0 -2024-06-20 15:00:00,11.01,11.01,11.0,11.0,1376.0,1513737.0 -2024-06-21 09:35:00,10.98,11.01,10.95,10.98,2649.0,2907158.0 -2024-06-21 09:40:00,10.98,11.04,10.98,11.03,1901.0,2093535.0 -2024-06-21 09:45:00,11.03,11.05,11.02,11.05,738.0,814164.0 -2024-06-21 09:50:00,11.06,11.08,11.05,11.07,1639.0,1814054.0 -2024-06-21 09:55:00,11.07,11.08,11.03,11.07,1445.0,1598150.0 -2024-06-21 10:00:00,11.07,11.08,11.05,11.07,634.0,701575.0 -2024-06-21 10:05:00,11.06,11.09,11.05,11.09,1222.0,1353174.0 -2024-06-21 10:10:00,11.09,11.1,11.06,11.07,717.0,794627.0 -2024-06-21 10:15:00,11.07,11.08,11.05,11.06,487.0,538835.0 -2024-06-21 10:20:00,11.06,11.06,11.02,11.02,584.0,644683.0 -2024-06-21 10:25:00,11.03,11.05,11.02,11.05,979.0,1080786.0 -2024-06-21 10:30:00,11.05,11.06,11.04,11.06,1236.0,1365238.0 -2024-06-21 10:35:00,11.06,11.06,11.03,11.05,342.0,377693.0 -2024-06-21 10:40:00,11.05,11.06,11.04,11.06,461.0,509531.0 -2024-06-21 10:45:00,11.06,11.06,11.03,11.04,394.0,435047.0 -2024-06-21 10:50:00,11.04,11.05,11.03,11.05,505.0,557412.0 -2024-06-21 10:55:00,11.05,11.06,11.03,11.05,728.0,804172.0 -2024-06-21 11:00:00,11.05,11.05,11.03,11.04,275.0,303638.0 -2024-06-21 11:05:00,11.03,11.05,11.03,11.03,260.0,286971.0 -2024-06-21 11:10:00,11.03,11.04,11.02,11.04,464.0,511921.0 -2024-06-21 11:15:00,11.04,11.05,11.03,11.05,493.0,544347.0 -2024-06-21 11:20:00,11.05,11.06,11.04,11.05,662.0,731504.0 -2024-06-21 11:25:00,11.05,11.05,11.03,11.04,312.0,344655.0 -2024-06-21 11:30:00,11.04,11.06,11.04,11.04,547.0,604516.0 -2024-06-21 13:05:00,11.04,11.04,11.03,11.04,360.0,397271.0 -2024-06-21 13:10:00,11.04,11.04,11.02,11.03,825.0,909626.0 -2024-06-21 13:15:00,11.03,11.03,11.02,11.02,285.0,314136.0 -2024-06-21 13:20:00,11.02,11.05,11.02,11.05,734.0,809721.0 -2024-06-21 13:25:00,11.05,11.08,11.03,11.07,982.0,1085879.0 -2024-06-21 13:30:00,11.07,11.07,11.05,11.06,211.0,233313.0 -2024-06-21 13:35:00,11.05,11.07,11.04,11.07,2775.0,3059822.0 -2024-06-21 13:40:00,11.07,11.08,11.06,11.07,887.0,981700.0 -2024-06-21 13:45:00,11.06,11.06,11.04,11.04,464.0,512905.0 -2024-06-21 13:50:00,11.05,11.07,11.04,11.07,818.0,903752.0 -2024-06-21 13:55:00,11.06,11.07,11.04,11.06,892.0,986208.0 -2024-06-21 14:00:00,11.06,11.06,11.04,11.06,381.0,421175.0 -2024-06-21 14:05:00,11.06,11.07,11.04,11.07,1200.0,1326678.0 -2024-06-21 14:10:00,11.07,11.07,11.04,11.04,1830.0,2021572.0 -2024-06-21 14:15:00,11.04,11.05,11.03,11.04,375.0,414093.0 -2024-06-21 14:20:00,11.04,11.05,11.03,11.05,352.0,388879.0 -2024-06-21 14:25:00,11.04,11.07,11.04,11.07,651.0,719623.0 -2024-06-21 14:30:00,11.05,11.07,11.05,11.07,256.0,283273.0 -2024-06-21 14:35:00,11.07,11.07,11.05,11.06,287.0,317430.0 -2024-06-21 14:40:00,11.06,11.06,11.05,11.06,440.0,486507.0 -2024-06-21 14:45:00,11.06,11.06,11.04,11.05,1263.0,1395975.0 -2024-06-21 14:50:00,11.04,11.05,11.04,11.04,1068.0,1179463.0 -2024-06-21 14:55:00,11.05,11.05,11.04,11.04,1384.0,1529031.0 -2024-06-21 15:00:00,11.04,11.06,11.04,11.05,1374.0,1518557.0 -2024-06-24 09:35:00,11.0,11.0,10.92,10.93,4093.0,4483667.0 -2024-06-24 09:40:00,10.93,10.97,10.92,10.95,3212.0,3512061.0 -2024-06-24 09:45:00,10.95,10.96,10.94,10.96,1298.0,1420804.0 -2024-06-24 09:50:00,10.96,10.96,10.89,10.89,6825.0,7460077.0 -2024-06-24 09:55:00,10.89,10.93,10.88,10.91,2557.0,2786688.0 -2024-06-24 10:00:00,10.89,10.89,10.87,10.89,3179.0,3459864.0 -2024-06-24 10:05:00,10.9,10.9,10.86,10.86,3257.0,3542590.0 -2024-06-24 10:10:00,10.87,10.87,10.82,10.85,2953.0,3203466.0 -2024-06-24 10:15:00,10.84,10.86,10.83,10.83,2526.0,2738528.0 -2024-06-24 10:20:00,10.82,10.85,10.8,10.81,3692.0,3995308.0 -2024-06-24 10:25:00,10.81,10.84,10.79,10.81,2544.0,2750965.0 -2024-06-24 10:30:00,10.81,10.84,10.8,10.81,1475.0,1594938.0 -2024-06-24 10:35:00,10.8,10.81,10.78,10.79,1369.0,1477893.0 -2024-06-24 10:40:00,10.78,10.8,10.76,10.78,1532.0,1651515.0 -2024-06-24 10:45:00,10.77,10.79,10.76,10.76,949.0,1021939.0 -2024-06-24 10:50:00,10.75,10.76,10.73,10.75,1542.0,1657182.0 -2024-06-24 10:55:00,10.75,10.77,10.74,10.76,874.0,939985.0 -2024-06-24 11:00:00,10.76,10.79,10.76,10.77,546.0,588261.0 -2024-06-24 11:05:00,10.77,10.79,10.76,10.76,1067.0,1149959.0 -2024-06-24 11:10:00,10.77,10.79,10.76,10.78,547.0,589417.0 -2024-06-24 11:15:00,10.79,10.83,10.77,10.82,1516.0,1636842.0 -2024-06-24 11:20:00,10.82,10.83,10.79,10.82,717.0,775248.0 -2024-06-24 11:25:00,10.82,10.84,10.8,10.83,632.0,683842.0 -2024-06-24 11:30:00,10.82,10.85,10.81,10.84,718.0,778040.0 -2024-06-24 13:05:00,10.84,10.85,10.82,10.82,786.0,852256.0 -2024-06-24 13:10:00,10.82,10.88,10.81,10.87,1170.0,1268216.0 -2024-06-24 13:15:00,10.87,10.89,10.87,10.88,1253.0,1363942.0 -2024-06-24 13:20:00,10.88,10.9,10.88,10.9,663.0,722203.0 -2024-06-24 13:25:00,10.88,10.9,10.87,10.88,566.0,615831.0 -2024-06-24 13:30:00,10.89,10.89,10.87,10.89,231.0,251370.0 -2024-06-24 13:35:00,10.89,10.89,10.87,10.89,158.0,171900.0 -2024-06-24 13:40:00,10.89,10.89,10.86,10.86,337.0,366327.0 -2024-06-24 13:45:00,10.87,10.87,10.85,10.85,431.0,468176.0 -2024-06-24 13:50:00,10.86,10.86,10.84,10.86,567.0,615070.0 -2024-06-24 13:55:00,10.85,10.86,10.83,10.84,231.0,250355.0 -2024-06-24 14:00:00,10.84,10.85,10.83,10.83,302.0,327148.0 -2024-06-24 14:05:00,10.83,10.86,10.83,10.85,485.0,526018.0 -2024-06-24 14:10:00,10.85,10.87,10.84,10.86,480.0,521290.0 -2024-06-24 14:15:00,10.87,10.87,10.83,10.84,432.0,468658.0 -2024-06-24 14:20:00,10.84,10.87,10.83,10.86,1034.0,1122480.0 -2024-06-24 14:25:00,10.86,10.88,10.85,10.86,1110.0,1206399.0 -2024-06-24 14:30:00,10.86,10.86,10.83,10.84,548.0,593955.0 -2024-06-24 14:35:00,10.84,10.85,10.82,10.85,1095.0,1185831.0 -2024-06-24 14:40:00,10.84,10.85,10.8,10.81,1270.0,1373275.0 -2024-06-24 14:45:00,10.81,10.83,10.79,10.81,1512.0,1633749.0 -2024-06-24 14:50:00,10.81,10.83,10.78,10.8,1368.0,1477133.0 -2024-06-24 14:55:00,10.8,10.8,10.78,10.79,1715.0,1850578.0 -2024-06-24 15:00:00,10.79,10.8,10.78,10.8,1971.0,2127522.0 -2024-06-25 09:35:00,10.78,10.86,10.78,10.84,2874.0,3109932.0 -2024-06-25 09:40:00,10.84,10.84,10.79,10.81,2942.0,3183972.0 -2024-06-25 09:45:00,10.8,10.82,10.79,10.8,1435.0,1549700.0 -2024-06-25 09:50:00,10.79,10.82,10.77,10.82,965.0,1041231.0 -2024-06-25 09:55:00,10.81,10.84,10.8,10.84,1078.0,1166544.0 -2024-06-25 10:00:00,10.83,10.84,10.82,10.82,786.0,850954.0 -2024-06-25 10:05:00,10.83,10.83,10.79,10.79,407.0,439813.0 -2024-06-25 10:10:00,10.79,10.8,10.77,10.77,1036.0,1117023.0 -2024-06-25 10:15:00,10.77,10.78,10.76,10.78,560.0,603166.0 -2024-06-25 10:20:00,10.78,10.81,10.77,10.8,850.0,917452.0 -2024-06-25 10:25:00,10.8,10.8,10.78,10.78,591.0,637801.0 -2024-06-25 10:30:00,10.78,10.78,10.75,10.75,1049.0,1129614.0 -2024-06-25 10:35:00,10.76,10.76,10.75,10.75,378.0,406524.0 -2024-06-25 10:40:00,10.75,10.75,10.73,10.74,794.0,853389.0 -2024-06-25 10:45:00,10.75,10.75,10.74,10.75,534.0,573806.0 -2024-06-25 10:50:00,10.74,10.77,10.74,10.75,688.0,739694.0 -2024-06-25 10:55:00,10.76,10.77,10.75,10.76,267.0,287269.0 -2024-06-25 11:00:00,10.76,10.77,10.75,10.77,413.0,444269.0 -2024-06-25 11:05:00,10.77,10.77,10.75,10.76,354.0,381125.0 -2024-06-25 11:10:00,10.76,10.77,10.75,10.76,548.0,589246.0 -2024-06-25 11:15:00,10.76,10.77,10.75,10.77,161.0,173244.0 -2024-06-25 11:20:00,10.76,10.76,10.74,10.75,717.0,770739.0 -2024-06-25 11:25:00,10.75,10.77,10.74,10.75,1060.0,1139564.0 -2024-06-25 11:30:00,10.74,10.76,10.74,10.75,1763.0,1895320.0 -2024-06-25 13:05:00,10.76,10.76,10.74,10.76,1084.0,1165763.0 -2024-06-25 13:10:00,10.75,10.78,10.75,10.77,530.0,570865.0 -2024-06-25 13:15:00,10.77,10.78,10.76,10.76,196.0,211041.0 -2024-06-25 13:20:00,10.76,10.79,10.75,10.79,1804.0,1943814.0 -2024-06-25 13:25:00,10.79,10.82,10.79,10.81,1035.0,1118848.0 -2024-06-25 13:30:00,10.81,10.82,10.79,10.79,547.0,591019.0 -2024-06-25 13:35:00,10.79,10.8,10.78,10.78,427.0,460616.0 -2024-06-25 13:40:00,10.78,10.79,10.77,10.78,203.0,218877.0 -2024-06-25 13:45:00,10.78,10.79,10.77,10.78,215.0,231756.0 -2024-06-25 13:50:00,10.79,10.79,10.77,10.77,247.0,266268.0 -2024-06-25 13:55:00,10.78,10.78,10.77,10.77,535.0,576217.0 -2024-06-25 14:00:00,10.77,10.77,10.75,10.75,783.0,842646.0 -2024-06-25 14:05:00,10.76,10.76,10.74,10.74,1477.0,1587487.0 -2024-06-25 14:10:00,10.74,10.75,10.73,10.73,1833.0,1968273.0 -2024-06-25 14:15:00,10.73,10.73,10.7,10.71,3718.0,3984256.0 -2024-06-25 14:20:00,10.7,10.7,10.68,10.69,2073.0,2216308.0 -2024-06-25 14:25:00,10.69,10.71,10.68,10.71,1095.0,1170831.0 -2024-06-25 14:30:00,10.71,10.74,10.71,10.72,1847.0,1980159.0 -2024-06-25 14:35:00,10.72,10.74,10.7,10.74,794.0,851325.0 -2024-06-25 14:40:00,10.74,10.74,10.72,10.73,794.0,851965.0 -2024-06-25 14:45:00,10.73,10.74,10.71,10.73,789.0,845945.0 -2024-06-25 14:50:00,10.72,10.74,10.72,10.73,589.0,631873.0 -2024-06-25 14:55:00,10.73,10.74,10.71,10.72,842.0,902657.0 -2024-06-25 15:00:00,10.71,10.74,10.71,10.74,1360.0,1460355.0 -2024-06-26 09:35:00,10.73,10.74,10.69,10.73,1885.0,2020689.0 -2024-06-26 09:40:00,10.72,10.8,10.72,10.8,2518.0,2710537.0 -2024-06-26 09:45:00,10.79,10.83,10.78,10.81,3320.0,3586272.0 -2024-06-26 09:50:00,10.81,10.82,10.78,10.8,1598.0,1725584.0 -2024-06-26 09:55:00,10.79,10.8,10.76,10.78,888.0,957446.0 -2024-06-26 10:00:00,10.77,10.77,10.75,10.75,1257.0,1352415.0 -2024-06-26 10:05:00,10.73,10.75,10.73,10.74,1306.0,1402518.0 -2024-06-26 10:10:00,10.73,10.75,10.72,10.74,1359.0,1458216.0 -2024-06-26 10:15:00,10.74,10.74,10.71,10.72,698.0,748870.0 -2024-06-26 10:20:00,10.72,10.73,10.71,10.72,447.0,479240.0 -2024-06-26 10:25:00,10.72,10.73,10.7,10.71,914.0,978891.0 -2024-06-26 10:30:00,10.72,10.73,10.71,10.73,473.0,507032.0 -2024-06-26 10:35:00,10.72,10.74,10.72,10.72,446.0,478580.0 -2024-06-26 10:40:00,10.72,10.75,10.72,10.73,481.0,516539.0 -2024-06-26 10:45:00,10.73,10.75,10.72,10.72,253.0,271442.0 -2024-06-26 10:50:00,10.72,10.73,10.7,10.7,1425.0,1526537.0 -2024-06-26 10:55:00,10.7,10.71,10.69,10.69,730.0,781014.0 -2024-06-26 11:00:00,10.69,10.7,10.68,10.7,559.0,597502.0 -2024-06-26 11:05:00,10.71,10.72,10.7,10.71,109.0,116781.0 -2024-06-26 11:10:00,10.7,10.7,10.7,10.7,198.0,211860.0 -2024-06-26 11:15:00,10.71,10.72,10.7,10.71,204.0,218628.0 -2024-06-26 11:20:00,10.71,10.73,10.71,10.73,59.0,63252.0 -2024-06-26 11:25:00,10.73,10.75,10.71,10.72,642.0,689040.0 -2024-06-26 11:30:00,10.72,10.74,10.72,10.74,284.0,304706.0 -2024-06-26 13:05:00,10.74,10.76,10.73,10.76,364.0,391056.0 -2024-06-26 13:10:00,10.76,10.8,10.76,10.79,1440.0,1552878.0 -2024-06-26 13:15:00,10.8,10.84,10.79,10.84,4283.0,4631720.0 -2024-06-26 13:20:00,10.84,10.84,10.79,10.8,1986.0,2148668.0 -2024-06-26 13:25:00,10.8,10.84,10.78,10.84,2430.0,2627411.0 -2024-06-26 13:30:00,10.84,10.9,10.83,10.86,3791.0,4118709.0 -2024-06-26 13:35:00,10.86,10.89,10.85,10.86,1377.0,1496493.0 -2024-06-26 13:40:00,10.86,10.9,10.86,10.88,1180.0,1283888.0 -2024-06-26 13:45:00,10.88,10.9,10.87,10.89,1529.0,1665466.0 -2024-06-26 13:50:00,10.89,10.89,10.86,10.86,410.0,445491.0 -2024-06-26 13:55:00,10.86,10.89,10.86,10.88,644.0,700660.0 -2024-06-26 14:00:00,10.88,10.91,10.88,10.91,1248.0,1359552.0 -2024-06-26 14:05:00,10.91,10.93,10.9,10.93,2252.0,2458953.0 -2024-06-26 14:10:00,10.92,10.93,10.91,10.93,1526.0,1666662.0 -2024-06-26 14:15:00,10.94,10.95,10.94,10.94,1239.0,1355751.0 -2024-06-26 14:20:00,10.95,10.96,10.94,10.95,1395.0,1527981.0 -2024-06-26 14:25:00,10.95,10.96,10.91,10.91,1933.0,2113366.0 -2024-06-26 14:30:00,10.93,10.95,10.92,10.93,1343.0,1468562.0 -2024-06-26 14:35:00,10.94,10.95,10.94,10.95,757.0,828489.0 -2024-06-26 14:40:00,10.95,10.95,10.92,10.93,2880.0,3151406.0 -2024-06-26 14:45:00,10.93,10.94,10.91,10.93,584.0,638099.0 -2024-06-26 14:50:00,10.94,10.94,10.92,10.93,935.0,1021768.0 -2024-06-26 14:55:00,10.92,10.95,10.92,10.95,1161.0,1269548.0 -2024-06-26 15:00:00,10.94,10.95,10.93,10.94,1533.0,1677121.0 -2024-06-27 09:35:00,10.9,10.95,10.88,10.89,3492.0,3812685.0 -2024-06-27 09:40:00,10.89,10.94,10.88,10.92,1614.0,1761373.0 -2024-06-27 09:45:00,10.92,10.95,10.91,10.94,1960.0,2142719.0 -2024-06-27 09:50:00,10.95,10.95,10.89,10.89,1450.0,1582764.0 -2024-06-27 09:55:00,10.9,10.92,10.86,10.87,1386.0,1509366.0 -2024-06-27 10:00:00,10.87,10.89,10.87,10.87,773.0,840578.0 -2024-06-27 10:05:00,10.86,10.87,10.83,10.84,1459.0,1583599.0 -2024-06-27 10:10:00,10.84,10.86,10.83,10.85,1578.0,1710919.0 -2024-06-27 10:15:00,10.85,10.85,10.83,10.83,834.0,903790.0 -2024-06-27 10:20:00,10.83,10.84,10.81,10.82,1468.0,1588873.0 -2024-06-27 10:25:00,10.83,10.85,10.83,10.84,626.0,678759.0 -2024-06-27 10:30:00,10.84,10.84,10.83,10.84,429.0,464880.0 -2024-06-27 10:35:00,10.83,10.84,10.82,10.83,571.0,618513.0 -2024-06-27 10:40:00,10.83,10.84,10.82,10.82,637.0,689486.0 -2024-06-27 10:45:00,10.82,10.84,10.81,10.83,767.0,829810.0 -2024-06-27 10:50:00,10.84,10.85,10.83,10.83,531.0,575489.0 -2024-06-27 10:55:00,10.83,10.84,10.82,10.84,1098.0,1188825.0 -2024-06-27 11:00:00,10.84,10.84,10.82,10.82,990.0,1071990.0 -2024-06-27 11:05:00,10.83,10.84,10.82,10.84,477.0,516567.0 -2024-06-27 11:10:00,10.83,10.84,10.82,10.82,345.0,373557.0 -2024-06-27 11:15:00,10.83,10.83,10.8,10.81,782.0,845658.0 -2024-06-27 11:20:00,10.82,10.82,10.8,10.81,361.0,390229.0 -2024-06-27 11:25:00,10.81,10.84,10.8,10.84,1289.0,1394340.0 -2024-06-27 11:30:00,10.84,10.86,10.84,10.86,528.0,572640.0 -2024-06-27 13:05:00,10.85,10.89,10.85,10.86,1160.0,1261480.0 -2024-06-27 13:10:00,10.87,10.88,10.84,10.85,351.0,381111.0 -2024-06-27 13:15:00,10.84,10.87,10.84,10.85,348.0,377656.0 -2024-06-27 13:20:00,10.85,10.88,10.85,10.87,780.0,847791.0 -2024-06-27 13:25:00,10.86,10.88,10.86,10.86,444.0,482768.0 -2024-06-27 13:30:00,10.87,10.87,10.85,10.85,292.0,317012.0 -2024-06-27 13:35:00,10.84,10.88,10.84,10.87,1277.0,1386244.0 -2024-06-27 13:40:00,10.87,10.89,10.86,10.88,972.0,1058158.0 -2024-06-27 13:45:00,10.88,10.9,10.88,10.88,593.0,645736.0 -2024-06-27 13:50:00,10.88,10.9,10.88,10.88,426.0,464056.0 -2024-06-27 13:55:00,10.88,10.89,10.87,10.89,358.0,389543.0 -2024-06-27 14:00:00,10.88,10.89,10.86,10.86,356.0,387207.0 -2024-06-27 14:05:00,10.87,10.87,10.85,10.87,634.0,688281.0 -2024-06-27 14:10:00,10.85,10.87,10.83,10.84,611.0,662522.0 -2024-06-27 14:15:00,10.84,10.87,10.84,10.84,466.0,505737.0 -2024-06-27 14:20:00,10.84,10.87,10.83,10.87,339.0,367770.0 -2024-06-27 14:25:00,10.87,10.88,10.86,10.87,841.0,914280.0 -2024-06-27 14:30:00,10.88,10.88,10.85,10.86,184.0,199877.0 -2024-06-27 14:35:00,10.87,10.88,10.85,10.86,729.0,792089.0 -2024-06-27 14:40:00,10.86,10.87,10.84,10.85,872.0,946593.0 -2024-06-27 14:45:00,10.84,10.85,10.82,10.83,1211.0,1310930.0 -2024-06-27 14:50:00,10.83,10.85,10.82,10.84,522.0,565554.0 -2024-06-27 14:55:00,10.85,10.85,10.83,10.85,1092.0,1183811.0 -2024-06-27 15:00:00,10.85,10.87,10.82,10.82,1977.0,2142644.0 -2024-06-28 09:35:00,10.81,10.88,10.81,10.85,4912.0,5327352.0 -2024-06-28 09:40:00,10.85,10.86,10.83,10.85,895.0,970401.0 -2024-06-28 09:45:00,10.86,10.9,10.85,10.88,3102.0,3374576.0 -2024-06-28 09:50:00,10.88,10.91,10.85,10.89,2160.0,2350604.0 -2024-06-28 09:55:00,10.89,10.92,10.89,10.91,936.0,1021115.0 -2024-06-28 10:00:00,10.9,10.93,10.89,10.92,1766.0,1927493.0 -2024-06-28 10:05:00,10.92,10.92,10.89,10.9,1859.0,2027228.0 -2024-06-28 10:10:00,10.9,10.91,10.89,10.91,822.0,895634.0 -2024-06-28 10:15:00,10.89,10.92,10.89,10.9,627.0,684177.0 -2024-06-28 10:20:00,10.9,10.91,10.89,10.89,755.0,822679.0 -2024-06-28 10:25:00,10.91,10.94,10.91,10.93,1589.0,1735513.0 -2024-06-28 10:30:00,10.93,10.94,10.92,10.94,1229.0,1344131.0 -2024-06-28 10:35:00,10.94,10.95,10.93,10.94,744.0,813853.0 -2024-06-28 10:40:00,10.93,10.95,10.93,10.94,969.0,1060256.0 -2024-06-28 10:45:00,10.93,10.94,10.92,10.92,380.0,415348.0 -2024-06-28 10:50:00,10.93,10.93,10.92,10.93,405.0,442304.0 -2024-06-28 10:55:00,10.92,10.94,10.92,10.93,876.0,956799.0 -2024-06-28 11:00:00,10.93,10.95,10.92,10.95,555.0,606735.0 -2024-06-28 11:05:00,10.94,10.94,10.91,10.91,520.0,568139.0 -2024-06-28 11:10:00,10.91,10.91,10.88,10.89,693.0,754878.0 -2024-06-28 11:15:00,10.89,10.89,10.88,10.88,417.0,453945.0 -2024-06-28 11:20:00,10.88,10.9,10.88,10.89,84.0,91487.0 -2024-06-28 11:25:00,10.89,10.9,10.89,10.89,206.0,224402.0 -2024-06-28 11:30:00,10.9,10.91,10.88,10.9,427.0,465291.0 -2024-06-28 13:05:00,10.9,10.92,10.89,10.89,730.0,795760.0 -2024-06-28 13:10:00,10.88,10.89,10.86,10.86,1419.0,1542736.0 -2024-06-28 13:15:00,10.86,10.87,10.83,10.83,2459.0,2666148.0 -2024-06-28 13:20:00,10.83,10.84,10.81,10.83,2862.0,3097616.0 -2024-06-28 13:25:00,10.82,10.83,10.8,10.8,3794.0,4101393.0 -2024-06-28 13:30:00,10.8,10.81,10.78,10.78,3307.0,3568649.0 -2024-06-28 13:35:00,10.78,10.85,10.78,10.84,3147.0,3402105.0 -2024-06-28 13:40:00,10.84,10.84,10.82,10.82,1210.0,1310800.0 -2024-06-28 13:45:00,10.82,10.85,10.82,10.84,823.0,891992.0 -2024-06-28 13:50:00,10.84,10.85,10.82,10.83,713.0,772348.0 -2024-06-28 13:55:00,10.83,10.84,10.82,10.83,569.0,616388.0 -2024-06-28 14:00:00,10.83,10.84,10.82,10.82,303.0,328051.0 -2024-06-28 14:05:00,10.82,10.82,10.8,10.82,853.0,922428.0 -2024-06-28 14:10:00,10.82,10.82,10.8,10.81,541.0,584618.0 -2024-06-28 14:15:00,10.81,10.81,10.78,10.78,1736.0,1872809.0 -2024-06-28 14:20:00,10.78,10.78,10.75,10.76,1780.0,1916475.0 -2024-06-28 14:25:00,10.76,10.76,10.73,10.75,1769.0,1900646.0 -2024-06-28 14:30:00,10.75,10.76,10.74,10.75,1964.0,2112329.0 -2024-06-28 14:35:00,10.75,10.76,10.74,10.76,889.0,955913.0 -2024-06-28 14:40:00,10.76,10.76,10.73,10.74,1368.0,1469670.0 -2024-06-28 14:45:00,10.74,10.77,10.74,10.75,1597.0,1717275.0 -2024-06-28 14:50:00,10.76,10.79,10.75,10.78,2367.0,2549263.0 -2024-06-28 14:55:00,10.79,10.8,10.77,10.78,1092.0,1177700.0 -2024-06-28 15:00:00,10.78,10.79,10.76,10.76,1138.0,1226174.0 -2024-07-01 09:35:00,10.77,10.8,10.72,10.79,1843.0,1983491.0 -2024-07-01 09:40:00,10.78,10.8,10.73,10.75,2053.0,2211558.0 -2024-07-01 09:45:00,10.75,10.76,10.71,10.72,2141.0,2296754.0 -2024-07-01 09:50:00,10.72,10.75,10.72,10.74,422.0,453171.0 -2024-07-01 09:55:00,10.74,10.77,10.73,10.74,2113.0,2271409.0 -2024-07-01 10:00:00,10.74,10.76,10.74,10.75,860.0,924122.0 -2024-07-01 10:05:00,10.74,10.74,10.7,10.7,2021.0,2166129.0 -2024-07-01 10:10:00,10.71,10.72,10.69,10.71,1744.0,1866950.0 -2024-07-01 10:15:00,10.71,10.71,10.68,10.68,966.0,1032992.0 -2024-07-01 10:20:00,10.68,10.7,10.68,10.68,939.0,1003284.0 -2024-07-01 10:25:00,10.68,10.69,10.66,10.67,1190.0,1270220.0 -2024-07-01 10:30:00,10.67,10.71,10.66,10.71,1555.0,1661395.0 -2024-07-01 10:35:00,10.71,10.71,10.68,10.69,1030.0,1101921.0 -2024-07-01 10:40:00,10.7,10.71,10.68,10.68,883.0,944105.0 -2024-07-01 10:45:00,10.69,10.72,10.69,10.71,1303.0,1395304.0 -2024-07-01 10:50:00,10.71,10.74,10.71,10.74,470.0,504170.0 -2024-07-01 10:55:00,10.74,10.79,10.72,10.78,1239.0,1332198.0 -2024-07-01 11:00:00,10.78,10.8,10.76,10.79,2881.0,3104504.0 -2024-07-01 11:05:00,10.79,10.8,10.78,10.78,923.0,995611.0 -2024-07-01 11:10:00,10.77,10.79,10.77,10.78,856.0,922008.0 -2024-07-01 11:15:00,10.78,10.82,10.78,10.81,1393.0,1504310.0 -2024-07-01 11:20:00,10.82,10.82,10.8,10.8,1352.0,1461419.0 -2024-07-01 11:25:00,10.82,10.83,10.81,10.82,575.0,622260.0 -2024-07-01 11:30:00,10.82,10.82,10.8,10.8,329.0,355652.0 -2024-07-01 13:05:00,10.81,10.85,10.8,10.85,2159.0,2335760.0 -2024-07-01 13:10:00,10.85,10.86,10.84,10.84,1177.0,1277255.0 -2024-07-01 13:15:00,10.84,10.86,10.84,10.85,1510.0,1638095.0 -2024-07-01 13:20:00,10.85,10.89,10.85,10.88,1759.0,1911621.0 -2024-07-01 13:25:00,10.88,10.9,10.87,10.88,1562.0,1699652.0 -2024-07-01 13:30:00,10.88,10.89,10.87,10.88,675.0,734717.0 -2024-07-01 13:35:00,10.89,10.9,10.89,10.9,852.0,928114.0 -2024-07-01 13:40:00,10.9,10.9,10.86,10.88,3273.0,3561026.0 -2024-07-01 13:45:00,10.89,10.89,10.88,10.89,562.0,611946.0 -2024-07-01 13:50:00,10.9,10.9,10.87,10.89,930.0,1012251.0 -2024-07-01 13:55:00,10.88,10.89,10.87,10.88,863.0,939220.0 -2024-07-01 14:00:00,10.89,10.9,10.88,10.9,732.0,797117.0 -2024-07-01 14:05:00,10.9,10.91,10.89,10.91,1105.0,1204559.0 -2024-07-01 14:10:00,10.91,10.93,10.9,10.92,1160.0,1266631.0 -2024-07-01 14:15:00,10.92,10.92,10.91,10.92,1205.0,1315452.0 -2024-07-01 14:20:00,10.93,10.93,10.89,10.89,631.0,688207.0 -2024-07-01 14:25:00,10.9,10.9,10.87,10.88,868.0,944568.0 -2024-07-01 14:30:00,10.88,10.89,10.87,10.88,931.0,1012567.0 -2024-07-01 14:35:00,10.89,10.9,10.88,10.89,1463.0,1593692.0 -2024-07-01 14:40:00,10.89,10.9,10.89,10.9,635.0,691936.0 -2024-07-01 14:45:00,10.9,10.9,10.88,10.89,1453.0,1581718.0 -2024-07-01 14:50:00,10.88,10.88,10.86,10.87,1703.0,1851587.0 -2024-07-01 14:55:00,10.87,10.89,10.87,10.87,1211.0,1317142.0 -2024-07-01 15:00:00,10.87,10.88,10.86,10.86,1491.0,1620192.0 -2024-07-02 09:35:00,10.86,10.88,10.83,10.88,2350.0,2550744.0 -2024-07-02 09:40:00,10.87,10.92,10.85,10.91,2451.0,2666168.0 -2024-07-02 09:45:00,10.91,10.92,10.87,10.9,1437.0,1566519.0 -2024-07-02 09:50:00,10.9,10.9,10.88,10.9,1131.0,1231876.0 -2024-07-02 09:55:00,10.89,10.9,10.87,10.88,962.0,1047022.0 -2024-07-02 10:00:00,10.88,10.92,10.88,10.91,4629.0,5043863.0 -2024-07-02 10:05:00,10.91,10.93,10.89,10.92,2042.0,2227941.0 -2024-07-02 10:10:00,10.92,10.93,10.91,10.93,1417.0,1547975.0 -2024-07-02 10:15:00,10.94,10.94,10.93,10.94,1455.0,1591295.0 -2024-07-02 10:20:00,10.94,10.95,10.92,10.94,1895.0,2072046.0 -2024-07-02 10:25:00,10.95,10.95,10.94,10.94,1225.0,1340405.0 -2024-07-02 10:30:00,10.94,10.94,10.91,10.94,1871.0,2044786.0 -2024-07-02 10:35:00,10.94,10.94,10.92,10.92,377.0,411965.0 -2024-07-02 10:40:00,10.92,10.93,10.91,10.91,499.0,544570.0 -2024-07-02 10:45:00,10.91,10.92,10.91,10.91,463.0,505263.0 -2024-07-02 10:50:00,10.91,10.92,10.9,10.91,461.0,502944.0 -2024-07-02 10:55:00,10.91,10.92,10.9,10.91,465.0,507185.0 -2024-07-02 11:00:00,10.91,10.91,10.9,10.91,638.0,695653.0 -2024-07-02 11:05:00,10.91,10.91,10.9,10.91,636.0,693330.0 -2024-07-02 11:10:00,10.9,10.92,10.89,10.9,707.0,771306.0 -2024-07-02 11:15:00,10.9,10.91,10.89,10.9,539.0,587560.0 -2024-07-02 11:20:00,10.9,10.91,10.9,10.9,164.0,178837.0 -2024-07-02 11:25:00,10.9,10.9,10.88,10.89,1739.0,1893178.0 -2024-07-02 11:30:00,10.88,10.9,10.88,10.9,532.0,579222.0 -2024-07-02 13:05:00,10.89,10.92,10.89,10.9,918.0,1000783.0 -2024-07-02 13:10:00,10.91,10.92,10.89,10.89,304.0,331509.0 -2024-07-02 13:15:00,10.9,10.92,10.9,10.91,686.0,748691.0 -2024-07-02 13:20:00,10.9,10.92,10.9,10.9,525.0,572586.0 -2024-07-02 13:25:00,10.9,10.9,10.89,10.89,1325.0,1443307.0 -2024-07-02 13:30:00,10.9,10.91,10.89,10.9,390.0,424906.0 -2024-07-02 13:35:00,10.89,10.91,10.89,10.91,242.0,263782.0 -2024-07-02 13:40:00,10.91,10.92,10.9,10.92,264.0,288026.0 -2024-07-02 13:45:00,10.9,10.92,10.9,10.91,504.0,549897.0 -2024-07-02 13:50:00,10.91,10.92,10.9,10.91,244.0,266258.0 -2024-07-02 13:55:00,10.9,10.92,10.9,10.92,319.0,347982.0 -2024-07-02 14:00:00,10.92,10.93,10.9,10.93,810.0,884580.0 -2024-07-02 14:05:00,10.92,10.93,10.9,10.9,1088.0,1187904.0 -2024-07-02 14:10:00,10.91,10.92,10.89,10.91,335.0,365319.0 -2024-07-02 14:15:00,10.9,10.91,10.9,10.9,298.0,325000.0 -2024-07-02 14:20:00,10.91,10.92,10.89,10.91,680.0,741484.0 -2024-07-02 14:25:00,10.9,10.91,10.89,10.89,540.0,588405.0 -2024-07-02 14:30:00,10.89,10.89,10.87,10.88,880.0,957618.0 -2024-07-02 14:35:00,10.88,10.89,10.86,10.87,1035.0,1125292.0 -2024-07-02 14:40:00,10.86,10.89,10.86,10.89,982.0,1067704.0 -2024-07-02 14:45:00,10.88,10.89,10.87,10.89,525.0,571385.0 -2024-07-02 14:50:00,10.88,10.89,10.88,10.88,553.0,601783.0 -2024-07-02 14:55:00,10.88,10.91,10.88,10.9,1483.0,1615999.0 -2024-07-02 15:00:00,10.89,10.91,10.88,10.88,1357.0,1478047.0 -2024-07-03 09:35:00,10.9,10.9,10.83,10.87,2668.0,2894960.0 -2024-07-03 09:40:00,10.87,10.9,10.84,10.88,1946.0,2114180.0 -2024-07-03 09:45:00,10.87,10.92,10.87,10.91,2077.0,2261673.0 -2024-07-03 09:50:00,10.92,10.94,10.89,10.93,2481.0,2707589.0 -2024-07-03 09:55:00,10.94,10.96,10.93,10.94,2154.0,2357499.0 -2024-07-03 10:00:00,10.93,10.95,10.92,10.93,616.0,673423.0 -2024-07-03 10:05:00,10.92,10.93,10.91,10.93,894.0,976005.0 -2024-07-03 10:10:00,10.93,10.94,10.92,10.93,474.0,518108.0 -2024-07-03 10:15:00,10.93,10.94,10.91,10.93,471.0,514682.0 -2024-07-03 10:20:00,10.93,10.93,10.91,10.92,612.0,668570.0 -2024-07-03 10:25:00,10.92,10.93,10.91,10.92,833.0,909668.0 -2024-07-03 10:30:00,10.92,10.93,10.92,10.92,297.0,324550.0 -2024-07-03 10:35:00,10.93,10.98,10.93,10.95,3374.0,3694639.0 -2024-07-03 10:40:00,10.96,10.97,10.95,10.97,1358.0,1487605.0 -2024-07-03 10:45:00,10.96,11.0,10.95,10.98,4770.0,5235244.0 -2024-07-03 10:50:00,10.99,10.99,10.97,10.98,1261.0,1385074.0 -2024-07-03 10:55:00,10.97,10.99,10.97,10.97,1781.0,1955678.0 -2024-07-03 11:00:00,10.98,10.99,10.97,10.97,643.0,706141.0 -2024-07-03 11:05:00,10.97,10.99,10.97,10.98,475.0,521517.0 -2024-07-03 11:10:00,10.98,11.03,10.98,11.02,3665.0,4032758.0 -2024-07-03 11:15:00,11.02,11.04,11.02,11.02,1743.0,1922504.0 -2024-07-03 11:20:00,11.03,11.03,11.02,11.02,625.0,689271.0 -2024-07-03 11:25:00,11.03,11.03,11.02,11.03,1001.0,1103543.0 -2024-07-03 11:30:00,11.02,11.04,11.02,11.04,944.0,1040906.0 -2024-07-03 13:05:00,11.03,11.04,11.02,11.03,1794.0,1979049.0 -2024-07-03 13:10:00,11.03,11.04,11.01,11.04,1801.0,1985668.0 -2024-07-03 13:15:00,11.04,11.05,11.03,11.05,1056.0,1166313.0 -2024-07-03 13:20:00,11.05,11.06,11.04,11.05,955.0,1055373.0 -2024-07-03 13:25:00,11.05,11.05,11.03,11.03,565.0,623412.0 -2024-07-03 13:30:00,11.04,11.04,11.02,11.03,459.0,506244.0 -2024-07-03 13:35:00,11.03,11.04,11.02,11.02,439.0,483979.0 -2024-07-03 13:40:00,11.02,11.03,11.01,11.02,554.0,610289.0 -2024-07-03 13:45:00,11.02,11.04,11.01,11.03,791.0,872429.0 -2024-07-03 13:50:00,11.02,11.02,11.0,11.0,1116.0,1228673.0 -2024-07-03 13:55:00,11.0,11.01,11.0,11.01,364.0,400625.0 -2024-07-03 14:00:00,11.0,11.01,10.99,11.01,684.0,752139.0 -2024-07-03 14:05:00,11.01,11.01,10.98,10.98,1352.0,1485817.0 -2024-07-03 14:10:00,10.98,11.0,10.98,11.0,644.0,707314.0 -2024-07-03 14:15:00,11.0,11.01,10.99,10.99,288.0,316750.0 -2024-07-03 14:20:00,10.99,11.0,10.98,11.0,230.0,252763.0 -2024-07-03 14:25:00,10.99,11.0,10.98,10.99,192.0,211087.0 -2024-07-03 14:30:00,10.99,10.99,10.97,10.98,539.0,591943.0 -2024-07-03 14:35:00,10.97,10.99,10.95,10.96,1520.0,1666866.0 -2024-07-03 14:40:00,10.96,10.96,10.95,10.96,590.0,646263.0 -2024-07-03 14:45:00,10.96,10.97,10.94,10.96,804.0,880802.0 -2024-07-03 14:50:00,10.96,10.97,10.95,10.97,468.0,512907.0 -2024-07-03 14:55:00,10.97,10.97,10.95,10.97,1271.0,1392839.0 -2024-07-03 15:00:00,10.96,10.97,10.95,10.97,1166.0,1278675.0 -2024-07-04 09:35:00,10.97,10.99,10.93,10.95,2908.0,3185297.0 -2024-07-04 09:40:00,10.95,10.96,10.92,10.93,2122.0,2320994.0 -2024-07-04 09:45:00,10.92,10.94,10.9,10.92,2221.0,2425223.0 -2024-07-04 09:50:00,10.92,10.92,10.89,10.91,1707.0,1860848.0 -2024-07-04 09:55:00,10.91,10.92,10.88,10.88,2087.0,2275084.0 -2024-07-04 10:00:00,10.88,10.91,10.88,10.89,1221.0,1329311.0 -2024-07-04 10:05:00,10.88,10.89,10.87,10.88,1005.0,1093321.0 -2024-07-04 10:10:00,10.88,10.89,10.86,10.88,1772.0,1926686.0 -2024-07-04 10:15:00,10.88,10.88,10.85,10.86,1120.0,1215925.0 -2024-07-04 10:20:00,10.86,10.89,10.85,10.85,1028.0,1117315.0 -2024-07-04 10:25:00,10.85,10.89,10.85,10.89,299.0,325167.0 -2024-07-04 10:30:00,10.88,10.88,10.85,10.86,571.0,620344.0 -2024-07-04 10:35:00,10.88,10.88,10.84,10.85,718.0,779223.0 -2024-07-04 10:40:00,10.85,10.86,10.84,10.85,580.0,629634.0 -2024-07-04 10:45:00,10.86,10.88,10.85,10.86,278.0,302131.0 -2024-07-04 10:50:00,10.88,10.89,10.87,10.87,374.0,406773.0 -2024-07-04 10:55:00,10.87,10.89,10.87,10.88,227.0,246962.0 -2024-07-04 11:00:00,10.88,10.88,10.85,10.86,870.0,945393.0 -2024-07-04 11:05:00,10.86,10.86,10.85,10.86,204.0,221481.0 -2024-07-04 11:10:00,10.85,10.86,10.8,10.83,5286.0,5718791.0 -2024-07-04 11:15:00,10.82,10.83,10.81,10.82,473.0,511678.0 -2024-07-04 11:20:00,10.82,10.83,10.81,10.81,667.0,721307.0 -2024-07-04 11:25:00,10.81,10.81,10.79,10.8,1105.0,1193721.0 -2024-07-04 11:30:00,10.8,10.81,10.78,10.8,926.0,999458.0 -2024-07-04 13:05:00,10.8,10.8,10.76,10.77,1494.0,1610863.0 -2024-07-04 13:10:00,10.76,10.79,10.76,10.77,550.0,592508.0 -2024-07-04 13:15:00,10.77,10.79,10.76,10.77,739.0,796143.0 -2024-07-04 13:20:00,10.78,10.78,10.75,10.76,1670.0,1797548.0 -2024-07-04 13:25:00,10.76,10.76,10.73,10.74,1551.0,1666356.0 -2024-07-04 13:30:00,10.74,10.75,10.73,10.74,845.0,907448.0 -2024-07-04 13:35:00,10.74,10.75,10.73,10.75,598.0,642714.0 -2024-07-04 13:40:00,10.75,10.76,10.74,10.75,1111.0,1193679.0 -2024-07-04 13:45:00,10.74,10.75,10.72,10.72,846.0,908185.0 -2024-07-04 13:50:00,10.73,10.78,10.73,10.77,2348.0,2525284.0 -2024-07-04 13:55:00,10.77,10.79,10.75,10.78,1835.0,1973901.0 -2024-07-04 14:00:00,10.78,10.78,10.74,10.75,1611.0,1733331.0 -2024-07-04 14:05:00,10.74,10.76,10.73,10.73,708.0,760666.0 -2024-07-04 14:10:00,10.74,10.74,10.72,10.72,1858.0,1994322.0 -2024-07-04 14:15:00,10.72,10.72,10.67,10.69,4016.0,4295928.0 -2024-07-04 14:20:00,10.69,10.71,10.67,10.69,2172.0,2321910.0 -2024-07-04 14:25:00,10.7,10.7,10.67,10.68,2667.0,2847859.0 -2024-07-04 14:30:00,10.68,10.69,10.66,10.66,1717.0,1832183.0 -2024-07-04 14:35:00,10.66,10.72,10.66,10.72,1645.0,1757163.0 -2024-07-04 14:40:00,10.71,10.73,10.7,10.72,640.0,685517.0 -2024-07-04 14:45:00,10.71,10.72,10.69,10.7,449.0,480879.0 -2024-07-04 14:50:00,10.7,10.72,10.69,10.71,1501.0,1606579.0 -2024-07-04 14:55:00,10.71,10.71,10.68,10.69,2019.0,2160223.0 -2024-07-04 15:00:00,10.68,10.69,10.67,10.67,2405.0,2567338.0 -2024-07-05 09:35:00,10.68,10.72,10.6,10.66,3161.0,3366769.0 -2024-07-05 09:40:00,10.66,10.69,10.64,10.68,2463.0,2625213.0 -2024-07-05 09:45:00,10.68,10.7,10.66,10.69,2495.0,2665274.0 -2024-07-05 09:50:00,10.7,10.74,10.7,10.71,1778.0,1905634.0 -2024-07-05 09:55:00,10.71,10.74,10.71,10.71,1488.0,1594736.0 -2024-07-05 10:00:00,10.7,10.71,10.67,10.69,1812.0,1936095.0 -2024-07-05 10:05:00,10.69,10.72,10.69,10.72,1749.0,1871469.0 -2024-07-05 10:10:00,10.71,10.77,10.71,10.76,1947.0,2090957.0 -2024-07-05 10:15:00,10.75,10.76,10.75,10.75,1137.0,1222993.0 -2024-07-05 10:20:00,10.76,10.77,10.75,10.77,1506.0,1620865.0 -2024-07-05 10:25:00,10.77,10.78,10.75,10.77,1493.0,1606745.0 -2024-07-05 10:30:00,10.78,10.78,10.76,10.77,1052.0,1133115.0 -2024-07-05 10:35:00,10.77,10.77,10.75,10.75,751.0,807640.0 -2024-07-05 10:40:00,10.74,10.77,10.73,10.76,878.0,944093.0 -2024-07-05 10:45:00,10.76,10.81,10.76,10.8,3378.0,3642878.0 -2024-07-05 10:50:00,10.79,10.82,10.79,10.81,2307.0,2492394.0 -2024-07-05 10:55:00,10.8,10.86,10.8,10.82,4341.0,4699027.0 -2024-07-05 11:00:00,10.82,10.84,10.79,10.79,408.0,441170.0 -2024-07-05 11:05:00,10.78,10.8,10.78,10.79,364.0,392802.0 -2024-07-05 11:10:00,10.79,10.8,10.77,10.78,313.0,337487.0 -2024-07-05 11:15:00,10.78,10.78,10.77,10.77,1081.0,1164748.0 -2024-07-05 11:20:00,10.77,10.79,10.77,10.78,454.0,489356.0 -2024-07-05 11:25:00,10.78,10.8,10.78,10.8,243.0,262197.0 -2024-07-05 11:30:00,10.79,10.8,10.78,10.79,225.0,242796.0 -2024-07-05 13:05:00,10.8,10.8,10.77,10.77,749.0,807655.0 -2024-07-05 13:10:00,10.77,10.77,10.75,10.77,1738.0,1869854.0 -2024-07-05 13:15:00,10.76,10.77,10.75,10.75,487.0,524031.0 -2024-07-05 13:20:00,10.75,10.77,10.75,10.76,178.0,191452.0 -2024-07-05 13:25:00,10.76,10.76,10.73,10.73,1402.0,1506560.0 -2024-07-05 13:30:00,10.73,10.73,10.71,10.71,724.0,776165.0 -2024-07-05 13:35:00,10.73,10.75,10.72,10.73,474.0,509063.0 -2024-07-05 13:40:00,10.73,10.74,10.72,10.74,157.0,168488.0 -2024-07-05 13:45:00,10.73,10.75,10.72,10.73,397.0,426257.0 -2024-07-05 13:50:00,10.73,10.75,10.73,10.75,1288.0,1383100.0 -2024-07-05 13:55:00,10.74,10.78,10.74,10.76,317.0,341254.0 -2024-07-05 14:00:00,10.75,10.78,10.75,10.78,690.0,743447.0 -2024-07-05 14:05:00,10.78,10.8,10.76,10.8,624.0,673278.0 -2024-07-05 14:10:00,10.81,10.82,10.8,10.8,974.0,1052312.0 -2024-07-05 14:15:00,10.81,10.81,10.78,10.78,506.0,546040.0 -2024-07-05 14:20:00,10.8,10.8,10.77,10.77,715.0,770621.0 -2024-07-05 14:25:00,10.76,10.78,10.76,10.77,277.0,298213.0 -2024-07-05 14:30:00,10.77,10.78,10.76,10.76,281.0,302536.0 -2024-07-05 14:35:00,10.76,10.77,10.76,10.76,387.0,416490.0 -2024-07-05 14:40:00,10.76,10.77,10.76,10.76,256.0,275539.0 -2024-07-05 14:45:00,10.76,10.77,10.75,10.77,291.0,313032.0 -2024-07-05 14:50:00,10.77,10.77,10.75,10.77,582.0,626238.0 -2024-07-05 14:55:00,10.76,10.78,10.76,10.78,887.0,955312.0 -2024-07-05 15:00:00,10.78,10.78,10.77,10.78,877.0,945279.0 -2024-07-08 09:35:00,10.79,10.79,10.72,10.76,1876.0,2018440.0 -2024-07-08 09:40:00,10.76,10.77,10.74,10.74,1263.0,1357394.0 -2024-07-08 09:45:00,10.72,10.74,10.69,10.7,3051.0,3268825.0 -2024-07-08 09:50:00,10.68,10.69,10.64,10.68,3518.0,3752900.0 -2024-07-08 09:55:00,10.67,10.68,10.65,10.66,1892.0,2017920.0 -2024-07-08 10:00:00,10.66,10.68,10.64,10.66,1456.0,1551789.0 -2024-07-08 10:05:00,10.66,10.66,10.63,10.64,2583.0,2749035.0 -2024-07-08 10:10:00,10.64,10.66,10.62,10.63,2696.0,2867337.0 -2024-07-08 10:15:00,10.63,10.65,10.62,10.65,858.0,912904.0 -2024-07-08 10:20:00,10.65,10.65,10.62,10.62,1596.0,1696404.0 -2024-07-08 10:25:00,10.63,10.64,10.62,10.62,954.0,1013744.0 -2024-07-08 10:30:00,10.62,10.63,10.61,10.61,1685.0,1788394.0 -2024-07-08 10:35:00,10.61,10.62,10.58,10.59,4104.0,4349515.0 -2024-07-08 10:40:00,10.59,10.6,10.56,10.58,1954.0,2066674.0 -2024-07-08 10:45:00,10.57,10.58,10.56,10.58,2405.0,2541312.0 -2024-07-08 10:50:00,10.57,10.59,10.57,10.58,2566.0,2713309.0 -2024-07-08 10:55:00,10.58,10.6,10.58,10.6,268.0,283905.0 -2024-07-08 11:00:00,10.6,10.61,10.59,10.61,368.0,390201.0 -2024-07-08 11:05:00,10.61,10.62,10.6,10.61,669.0,709951.0 -2024-07-08 11:10:00,10.61,10.64,10.6,10.64,430.0,456618.0 -2024-07-08 11:15:00,10.64,10.65,10.61,10.61,417.0,443354.0 -2024-07-08 11:20:00,10.62,10.62,10.6,10.6,293.0,310772.0 -2024-07-08 11:25:00,10.61,10.62,10.6,10.61,452.0,479455.0 -2024-07-08 11:30:00,10.62,10.62,10.6,10.6,197.0,208974.0 -2024-07-08 13:05:00,10.61,10.61,10.59,10.59,841.0,891530.0 -2024-07-08 13:10:00,10.59,10.6,10.58,10.59,478.0,506142.0 -2024-07-08 13:15:00,10.59,10.6,10.58,10.6,385.0,407836.0 -2024-07-08 13:20:00,10.6,10.6,10.59,10.59,65.0,68868.0 -2024-07-08 13:25:00,10.59,10.6,10.58,10.59,313.0,331507.0 -2024-07-08 13:30:00,10.59,10.59,10.54,10.57,2369.0,2502370.0 -2024-07-08 13:35:00,10.55,10.59,10.55,10.59,512.0,541240.0 -2024-07-08 13:40:00,10.58,10.59,10.58,10.59,600.0,635092.0 -2024-07-08 13:45:00,10.59,10.59,10.56,10.57,598.0,632597.0 -2024-07-08 13:50:00,10.56,10.57,10.56,10.57,128.0,135200.0 -2024-07-08 13:55:00,10.57,10.57,10.53,10.53,1943.0,2047839.0 -2024-07-08 14:00:00,10.54,10.54,10.53,10.54,567.0,597378.0 -2024-07-08 14:05:00,10.53,10.55,10.53,10.55,1149.0,1210370.0 -2024-07-08 14:10:00,10.54,10.55,10.52,10.53,501.0,527967.0 -2024-07-08 14:15:00,10.53,10.54,10.53,10.53,170.0,179111.0 -2024-07-08 14:20:00,10.54,10.55,10.52,10.53,912.0,960400.0 -2024-07-08 14:25:00,10.53,10.53,10.52,10.53,787.0,828251.0 -2024-07-08 14:30:00,10.53,10.54,10.52,10.52,491.0,516804.0 -2024-07-08 14:35:00,10.53,10.54,10.52,10.53,1049.0,1105195.0 -2024-07-08 14:40:00,10.54,10.54,10.51,10.52,1191.0,1253437.0 -2024-07-08 14:45:00,10.51,10.52,10.5,10.51,1641.0,1724603.0 -2024-07-08 14:50:00,10.52,10.53,10.5,10.52,996.0,1047557.0 -2024-07-08 14:55:00,10.53,10.55,10.52,10.54,1867.0,1967797.0 -2024-07-08 15:00:00,10.55,10.55,10.53,10.54,1298.0,1368185.0 -2024-07-09 09:35:00,10.53,10.62,10.53,10.57,3327.0,3519619.0 -2024-07-09 09:40:00,10.58,10.61,10.56,10.61,1912.0,2021866.0 -2024-07-09 09:45:00,10.6,10.62,10.57,10.58,1393.0,1476300.0 -2024-07-09 09:50:00,10.56,10.6,10.55,10.57,1555.0,1643491.0 -2024-07-09 09:55:00,10.57,10.59,10.54,10.55,861.0,909491.0 -2024-07-09 10:00:00,10.55,10.55,10.48,10.49,1522.0,1600408.0 -2024-07-09 10:05:00,10.49,10.49,10.46,10.46,2169.0,2271516.0 -2024-07-09 10:10:00,10.46,10.46,10.41,10.41,3412.0,3560018.0 -2024-07-09 10:15:00,10.42,10.42,10.39,10.41,2996.0,3117497.0 -2024-07-09 10:20:00,10.41,10.41,10.37,10.4,2092.0,2173427.0 -2024-07-09 10:25:00,10.4,10.4,10.37,10.38,1564.0,1624253.0 -2024-07-09 10:30:00,10.38,10.38,10.33,10.33,3070.0,3179748.0 -2024-07-09 10:35:00,10.33,10.34,10.32,10.33,3269.0,3375685.0 -2024-07-09 10:40:00,10.32,10.33,10.29,10.31,4209.0,4339847.0 -2024-07-09 10:45:00,10.3,10.31,10.28,10.28,1749.0,1801003.0 -2024-07-09 10:50:00,10.28,10.3,10.26,10.28,2003.0,2058711.0 -2024-07-09 10:55:00,10.29,10.29,10.27,10.29,1121.0,1152321.0 -2024-07-09 11:00:00,10.29,10.29,10.24,10.27,2202.0,2260881.0 -2024-07-09 11:05:00,10.27,10.34,10.27,10.34,1361.0,1403514.0 -2024-07-09 11:10:00,10.34,10.36,10.34,10.35,1242.0,1285195.0 -2024-07-09 11:15:00,10.35,10.36,10.32,10.35,1260.0,1302408.0 -2024-07-09 11:20:00,10.36,10.46,10.35,10.45,3189.0,3323332.0 -2024-07-09 11:25:00,10.45,10.47,10.4,10.4,2023.0,2113503.0 -2024-07-09 11:30:00,10.4,10.41,10.37,10.41,534.0,555030.0 -2024-07-09 13:05:00,10.4,10.46,10.4,10.46,1252.0,1307531.0 -2024-07-09 13:10:00,10.46,10.47,10.43,10.44,975.0,1018822.0 -2024-07-09 13:15:00,10.44,10.44,10.4,10.4,2434.0,2535575.0 -2024-07-09 13:20:00,10.42,10.44,10.41,10.43,340.0,354460.0 -2024-07-09 13:25:00,10.42,10.45,10.42,10.44,859.0,896813.0 -2024-07-09 13:30:00,10.44,10.45,10.41,10.45,931.0,971144.0 -2024-07-09 13:35:00,10.45,10.49,10.45,10.49,1330.0,1393022.0 -2024-07-09 13:40:00,10.48,10.49,10.47,10.49,1090.0,1142862.0 -2024-07-09 13:45:00,10.48,10.54,10.48,10.54,1861.0,1955380.0 -2024-07-09 13:50:00,10.54,10.55,10.52,10.54,1949.0,2053176.0 -2024-07-09 13:55:00,10.53,10.55,10.51,10.52,2865.0,3015859.0 -2024-07-09 14:00:00,10.52,10.54,10.51,10.52,1025.0,1078670.0 -2024-07-09 14:05:00,10.53,10.57,10.53,10.57,1519.0,1604052.0 -2024-07-09 14:10:00,10.57,10.58,10.56,10.56,1369.0,1446944.0 -2024-07-09 14:15:00,10.57,10.57,10.55,10.57,1367.0,1444127.0 -2024-07-09 14:20:00,10.57,10.58,10.56,10.57,576.0,608714.0 -2024-07-09 14:25:00,10.56,10.57,10.56,10.56,1204.0,1272133.0 -2024-07-09 14:30:00,10.55,10.57,10.55,10.56,744.0,785809.0 -2024-07-09 14:35:00,10.57,10.57,10.56,10.56,1162.0,1227687.0 -2024-07-09 14:40:00,10.56,10.57,10.52,10.53,1375.0,1449840.0 -2024-07-09 14:45:00,10.53,10.54,10.52,10.53,564.0,594052.0 -2024-07-09 14:50:00,10.53,10.54,10.52,10.52,864.0,909501.0 -2024-07-09 14:55:00,10.52,10.56,10.52,10.55,2702.0,2847419.0 -2024-07-09 15:00:00,10.55,10.55,10.54,10.54,1159.0,1222271.0 -2024-07-10 09:35:00,10.48,10.48,10.35,10.37,7327.0,7624027.0 -2024-07-10 09:40:00,10.38,10.44,10.37,10.44,3427.0,3561567.0 -2024-07-10 09:45:00,10.44,10.46,10.42,10.43,1839.0,1919385.0 -2024-07-10 09:50:00,10.43,10.5,10.43,10.5,3730.0,3900131.0 -2024-07-10 09:55:00,10.49,10.5,10.47,10.47,2522.0,2643842.0 -2024-07-10 10:00:00,10.48,10.51,10.46,10.46,1508.0,1581131.0 -2024-07-10 10:05:00,10.46,10.47,10.46,10.47,1008.0,1054384.0 -2024-07-10 10:10:00,10.47,10.47,10.45,10.45,1695.0,1773182.0 -2024-07-10 10:15:00,10.46,10.46,10.43,10.44,2095.0,2187845.0 -2024-07-10 10:20:00,10.45,10.45,10.42,10.43,1326.0,1383375.0 -2024-07-10 10:25:00,10.43,10.43,10.39,10.39,2020.0,2102798.0 -2024-07-10 10:30:00,10.4,10.4,10.31,10.33,7663.0,7927625.0 -2024-07-10 10:35:00,10.32,10.35,10.31,10.33,4948.0,5109220.0 -2024-07-10 10:40:00,10.32,10.33,10.18,10.22,11024.0,11308732.0 -2024-07-10 10:45:00,10.23,10.26,10.21,10.25,4788.0,4898809.0 -2024-07-10 10:50:00,10.25,10.25,10.22,10.23,1916.0,1960327.0 -2024-07-10 10:55:00,10.22,10.24,10.22,10.23,1679.0,1717372.0 -2024-07-10 11:00:00,10.24,10.24,10.19,10.21,3998.0,4079745.0 -2024-07-10 11:05:00,10.22,10.22,10.2,10.21,1206.0,1230683.0 -2024-07-10 11:10:00,10.21,10.23,10.19,10.23,1522.0,1553598.0 -2024-07-10 11:15:00,10.22,10.23,10.2,10.23,1236.0,1262112.0 -2024-07-10 11:20:00,10.22,10.23,10.22,10.23,502.0,513275.0 -2024-07-10 11:25:00,10.23,10.24,10.23,10.23,439.0,449215.0 -2024-07-10 11:30:00,10.24,10.25,10.23,10.25,839.0,859406.0 -2024-07-10 13:05:00,10.25,10.25,10.22,10.23,1124.0,1150912.0 -2024-07-10 13:10:00,10.23,10.27,10.23,10.25,988.0,1012692.0 -2024-07-10 13:15:00,10.25,10.31,10.25,10.3,1245.0,1280532.0 -2024-07-10 13:20:00,10.31,10.31,10.26,10.27,985.0,1012555.0 -2024-07-10 13:25:00,10.27,10.3,10.27,10.29,666.0,684428.0 -2024-07-10 13:30:00,10.28,10.3,10.28,10.3,872.0,897523.0 -2024-07-10 13:35:00,10.29,10.31,10.27,10.27,1014.0,1043868.0 -2024-07-10 13:40:00,10.27,10.28,10.25,10.25,730.0,749619.0 -2024-07-10 13:45:00,10.25,10.27,10.24,10.25,800.0,820310.0 -2024-07-10 13:50:00,10.25,10.26,10.24,10.24,607.0,622273.0 -2024-07-10 13:55:00,10.24,10.25,10.24,10.25,2173.0,2226728.0 -2024-07-10 14:00:00,10.25,10.25,10.22,10.24,716.0,732822.0 -2024-07-10 14:05:00,10.24,10.25,10.24,10.25,534.0,547038.0 -2024-07-10 14:10:00,10.25,10.26,10.24,10.26,1312.0,1344641.0 -2024-07-10 14:15:00,10.27,10.27,10.24,10.24,468.0,480032.0 -2024-07-10 14:20:00,10.25,10.25,10.22,10.24,1692.0,1731958.0 -2024-07-10 14:25:00,10.23,10.24,10.23,10.24,594.0,608098.0 -2024-07-10 14:30:00,10.24,10.25,10.23,10.23,1043.0,1068429.0 -2024-07-10 14:35:00,10.24,10.24,10.22,10.22,806.0,823985.0 -2024-07-10 14:40:00,10.22,10.23,10.21,10.21,2392.0,2443490.0 -2024-07-10 14:45:00,10.22,10.22,10.21,10.22,560.0,572084.0 -2024-07-10 14:50:00,10.23,10.24,10.22,10.23,2508.0,2565081.0 -2024-07-10 14:55:00,10.22,10.23,10.22,10.23,1823.0,1863991.0 -2024-07-10 15:00:00,10.22,10.23,10.22,10.23,1693.0,1731757.0 -2024-07-11 09:35:00,10.37,10.45,10.36,10.39,15451.0,16076145.0 -2024-07-11 09:40:00,10.4,10.41,10.38,10.38,3316.0,3445046.0 -2024-07-11 09:45:00,10.38,10.4,10.36,10.38,3623.0,3760284.0 -2024-07-11 09:50:00,10.39,10.41,10.38,10.38,1804.0,1874715.0 -2024-07-11 09:55:00,10.38,10.39,10.34,10.35,2627.0,2720927.0 -2024-07-11 10:00:00,10.35,10.37,10.33,10.33,5360.0,5545112.0 -2024-07-11 10:05:00,10.34,10.37,10.32,10.35,3118.0,3224468.0 -2024-07-11 10:10:00,10.37,10.39,10.35,10.37,2541.0,2634754.0 -2024-07-11 10:15:00,10.37,10.39,10.36,10.38,3289.0,3412126.0 -2024-07-11 10:20:00,10.38,10.39,10.36,10.38,2615.0,2713296.0 -2024-07-11 10:25:00,10.38,10.39,10.36,10.37,2505.0,2597944.0 -2024-07-11 10:30:00,10.36,10.38,10.36,10.37,608.0,630535.0 -2024-07-11 10:35:00,10.38,10.42,10.38,10.4,3609.0,3754553.0 -2024-07-11 10:40:00,10.4,10.43,10.4,10.43,1709.0,1779939.0 -2024-07-11 10:45:00,10.43,10.43,10.41,10.42,849.0,884675.0 -2024-07-11 10:50:00,10.43,10.45,10.43,10.44,2267.0,2366587.0 -2024-07-11 10:55:00,10.44,10.45,10.42,10.42,1657.0,1729169.0 -2024-07-11 11:00:00,10.42,10.42,10.41,10.42,1027.0,1069510.0 -2024-07-11 11:05:00,10.41,10.43,10.39,10.39,2318.0,2410859.0 -2024-07-11 11:10:00,10.39,10.44,10.39,10.44,2385.0,2483740.0 -2024-07-11 11:15:00,10.43,10.44,10.42,10.43,2234.0,2330490.0 -2024-07-11 11:20:00,10.44,10.46,10.43,10.43,2098.0,2191337.0 -2024-07-11 11:25:00,10.44,10.45,10.43,10.43,884.0,922938.0 -2024-07-11 11:30:00,10.43,10.44,10.42,10.43,820.0,855092.0 -2024-07-11 13:05:00,10.44,10.44,10.41,10.41,807.0,840857.0 -2024-07-11 13:10:00,10.41,10.42,10.4,10.42,889.0,925712.0 -2024-07-11 13:15:00,10.41,10.42,10.4,10.4,589.0,613095.0 -2024-07-11 13:20:00,10.41,10.42,10.38,10.38,1164.0,1210140.0 -2024-07-11 13:25:00,10.38,10.41,10.38,10.4,1043.0,1084039.0 -2024-07-11 13:30:00,10.39,10.41,10.39,10.4,620.0,644277.0 -2024-07-11 13:35:00,10.38,10.4,10.38,10.4,837.0,869493.0 -2024-07-11 13:40:00,10.39,10.4,10.38,10.4,1468.0,1524782.0 -2024-07-11 13:45:00,10.39,10.4,10.38,10.39,757.0,786392.0 -2024-07-11 13:50:00,10.4,10.4,10.38,10.38,904.0,938948.0 -2024-07-11 13:55:00,10.39,10.41,10.38,10.4,731.0,759609.0 -2024-07-11 14:00:00,10.4,10.41,10.39,10.41,684.0,710669.0 -2024-07-11 14:05:00,10.39,10.41,10.39,10.39,851.0,884721.0 -2024-07-11 14:10:00,10.39,10.4,10.38,10.38,1533.0,1592735.0 -2024-07-11 14:15:00,10.38,10.4,10.38,10.38,662.0,687339.0 -2024-07-11 14:20:00,10.38,10.39,10.37,10.39,943.0,978965.0 -2024-07-11 14:25:00,10.38,10.39,10.38,10.38,940.0,976071.0 -2024-07-11 14:30:00,10.38,10.39,10.37,10.39,349.0,362390.0 -2024-07-11 14:35:00,10.39,10.4,10.38,10.39,1748.0,1816188.0 -2024-07-11 14:40:00,10.38,10.4,10.38,10.38,578.0,600427.0 -2024-07-11 14:45:00,10.38,10.4,10.38,10.39,960.0,997348.0 -2024-07-11 14:50:00,10.39,10.4,10.38,10.39,643.0,668252.0 -2024-07-11 14:55:00,10.4,10.4,10.38,10.4,2594.0,2695804.0 -2024-07-11 15:00:00,10.4,10.4,10.38,10.4,1530.0,1590637.0 -2024-07-12 09:35:00,10.38,10.42,10.35,10.41,3569.0,3707440.0 -2024-07-12 09:40:00,10.4,10.45,10.38,10.45,3707.0,3857691.0 -2024-07-12 09:45:00,10.44,10.48,10.43,10.46,2525.0,2640921.0 -2024-07-12 09:50:00,10.46,10.47,10.42,10.44,1591.0,1661426.0 -2024-07-12 09:55:00,10.44,10.48,10.44,10.48,3042.0,3183222.0 -2024-07-12 10:00:00,10.47,10.47,10.44,10.46,1159.0,1211614.0 -2024-07-12 10:05:00,10.46,10.46,10.42,10.42,1104.0,1152444.0 -2024-07-12 10:10:00,10.42,10.45,10.42,10.45,1072.0,1118806.0 -2024-07-12 10:15:00,10.46,10.46,10.45,10.45,1132.0,1183301.0 -2024-07-12 10:20:00,10.46,10.48,10.45,10.45,1352.0,1414504.0 -2024-07-12 10:25:00,10.46,10.46,10.43,10.44,848.0,885988.0 -2024-07-12 10:30:00,10.44,10.44,10.42,10.43,2063.0,2152426.0 -2024-07-12 10:35:00,10.43,10.44,10.42,10.42,970.0,1011724.0 -2024-07-12 10:40:00,10.42,10.43,10.4,10.41,2793.0,2908562.0 -2024-07-12 10:45:00,10.4,10.42,10.4,10.42,914.0,951601.0 -2024-07-12 10:50:00,10.41,10.42,10.41,10.41,1222.0,1272142.0 -2024-07-12 10:55:00,10.4,10.4,10.37,10.39,1625.0,1687756.0 -2024-07-12 11:00:00,10.38,10.39,10.36,10.38,2283.0,2369528.0 -2024-07-12 11:05:00,10.38,10.39,10.38,10.38,549.0,570314.0 -2024-07-12 11:10:00,10.39,10.39,10.37,10.38,605.0,627914.0 -2024-07-12 11:15:00,10.38,10.38,10.37,10.37,315.0,326905.0 -2024-07-12 11:20:00,10.37,10.38,10.36,10.36,522.0,541173.0 -2024-07-12 11:25:00,10.36,10.38,10.36,10.38,411.0,426237.0 -2024-07-12 11:30:00,10.38,10.38,10.36,10.37,393.0,407609.0 -2024-07-12 13:05:00,10.37,10.38,10.37,10.37,766.0,794328.0 -2024-07-12 13:10:00,10.38,10.38,10.37,10.38,459.0,476210.0 -2024-07-12 13:15:00,10.37,10.39,10.37,10.39,445.0,462018.0 -2024-07-12 13:20:00,10.39,10.39,10.36,10.37,713.0,739329.0 -2024-07-12 13:25:00,10.36,10.37,10.36,10.36,226.0,234345.0 -2024-07-12 13:30:00,10.36,10.37,10.36,10.37,254.0,263374.0 -2024-07-12 13:35:00,10.37,10.38,10.36,10.37,1014.0,1051480.0 -2024-07-12 13:40:00,10.37,10.39,10.36,10.38,1520.0,1575883.0 -2024-07-12 13:45:00,10.38,10.4,10.37,10.4,717.0,744450.0 -2024-07-12 13:50:00,10.4,10.41,10.39,10.41,1381.0,1437015.0 -2024-07-12 13:55:00,10.41,10.45,10.41,10.44,2454.0,2560872.0 -2024-07-12 14:00:00,10.44,10.44,10.42,10.44,573.0,597841.0 -2024-07-12 14:05:00,10.44,10.46,10.42,10.45,2195.0,2291424.0 -2024-07-12 14:10:00,10.45,10.48,10.45,10.48,3091.0,3235293.0 -2024-07-12 14:15:00,10.48,10.5,10.46,10.49,2388.0,2502943.0 -2024-07-12 14:20:00,10.49,10.5,10.47,10.47,1458.0,1528983.0 -2024-07-12 14:25:00,10.47,10.49,10.47,10.48,515.0,539640.0 -2024-07-12 14:30:00,10.47,10.47,10.44,10.45,1175.0,1228654.0 -2024-07-12 14:35:00,10.47,10.47,10.42,10.42,1056.0,1101947.0 -2024-07-12 14:40:00,10.43,10.44,10.41,10.43,1018.0,1060727.0 -2024-07-12 14:45:00,10.44,10.44,10.41,10.41,333.0,347016.0 -2024-07-12 14:50:00,10.42,10.43,10.41,10.43,601.0,626257.0 -2024-07-12 14:55:00,10.43,10.43,10.42,10.42,835.0,870464.0 -2024-07-12 15:00:00,10.43,10.45,10.42,10.43,2173.0,2267683.0 -2024-07-15 09:35:00,10.47,10.71,10.47,10.68,19564.0,20789180.0 -2024-07-15 09:40:00,10.68,10.72,10.63,10.64,10866.0,11612143.0 -2024-07-15 09:45:00,10.64,10.64,10.6,10.61,3702.0,3929983.0 -2024-07-15 09:50:00,10.6,10.61,10.58,10.6,3645.0,3862960.0 -2024-07-15 09:55:00,10.59,10.62,10.59,10.61,2195.0,2327797.0 -2024-07-15 10:00:00,10.6,10.61,10.57,10.58,2565.0,2716577.0 -2024-07-15 10:05:00,10.57,10.57,10.54,10.55,2552.0,2692938.0 -2024-07-15 10:10:00,10.55,10.56,10.53,10.54,2513.0,2649679.0 -2024-07-15 10:15:00,10.53,10.63,10.53,10.6,4871.0,5159016.0 -2024-07-15 10:20:00,10.61,10.61,10.57,10.57,1299.0,1374835.0 -2024-07-15 10:25:00,10.58,10.58,10.56,10.56,1523.0,1610194.0 -2024-07-15 10:30:00,10.56,10.57,10.55,10.55,543.0,573275.0 -2024-07-15 10:35:00,10.55,10.55,10.52,10.53,1155.0,1216506.0 -2024-07-15 10:40:00,10.53,10.55,10.53,10.54,1392.0,1466441.0 -2024-07-15 10:45:00,10.54,10.54,10.52,10.52,752.0,792283.0 -2024-07-15 10:50:00,10.53,10.53,10.51,10.53,866.0,911133.0 -2024-07-15 10:55:00,10.52,10.53,10.51,10.52,338.0,355649.0 -2024-07-15 11:00:00,10.52,10.53,10.51,10.52,1313.0,1381018.0 -2024-07-15 11:05:00,10.52,10.52,10.48,10.48,1870.0,1963117.0 -2024-07-15 11:10:00,10.49,10.54,10.49,10.53,1480.0,1555231.0 -2024-07-15 11:15:00,10.54,10.56,10.51,10.51,1578.0,1663424.0 -2024-07-15 11:20:00,10.52,10.55,10.51,10.55,1052.0,1107327.0 -2024-07-15 11:25:00,10.55,10.56,10.53,10.53,649.0,684511.0 -2024-07-15 11:30:00,10.54,10.54,10.51,10.54,629.0,661965.0 -2024-07-15 13:05:00,10.54,10.56,10.52,10.56,1066.0,1124135.0 -2024-07-15 13:10:00,10.56,10.58,10.53,10.53,1355.0,1430689.0 -2024-07-15 13:15:00,10.54,10.54,10.51,10.52,832.0,875558.0 -2024-07-15 13:20:00,10.52,10.53,10.51,10.52,938.0,987245.0 -2024-07-15 13:25:00,10.52,10.53,10.51,10.52,299.0,314509.0 -2024-07-15 13:30:00,10.51,10.52,10.51,10.52,304.0,319705.0 -2024-07-15 13:35:00,10.52,10.53,10.5,10.5,1073.0,1127731.0 -2024-07-15 13:40:00,10.5,10.53,10.49,10.53,1476.0,1551089.0 -2024-07-15 13:45:00,10.53,10.53,10.5,10.5,1663.0,1748948.0 -2024-07-15 13:50:00,10.49,10.5,10.45,10.47,3136.0,3285101.0 -2024-07-15 13:55:00,10.46,10.48,10.45,10.48,851.0,890384.0 -2024-07-15 14:00:00,10.48,10.51,10.47,10.5,978.0,1025134.0 -2024-07-15 14:05:00,10.5,10.5,10.48,10.49,384.0,402918.0 -2024-07-15 14:10:00,10.49,10.51,10.48,10.5,462.0,485007.0 -2024-07-15 14:15:00,10.51,10.52,10.5,10.52,657.0,690632.0 -2024-07-15 14:20:00,10.52,10.52,10.5,10.52,887.0,932741.0 -2024-07-15 14:25:00,10.51,10.52,10.49,10.5,1398.0,1468094.0 -2024-07-15 14:30:00,10.5,10.5,10.48,10.5,873.0,915692.0 -2024-07-15 14:35:00,10.5,10.5,10.48,10.48,585.0,613793.0 -2024-07-15 14:40:00,10.49,10.51,10.48,10.51,979.0,1027161.0 -2024-07-15 14:45:00,10.51,10.52,10.5,10.5,1895.0,1991216.0 -2024-07-15 14:50:00,10.52,10.52,10.5,10.51,1048.0,1101838.0 -2024-07-15 14:55:00,10.5,10.5,10.49,10.5,1447.0,1518688.0 -2024-07-15 15:00:00,10.5,10.51,10.49,10.5,1463.0,1536046.0 -2024-07-16 09:35:00,10.51,10.53,10.38,10.44,7816.0,8165307.0 -2024-07-16 09:40:00,10.44,10.52,10.44,10.5,3729.0,3907407.0 -2024-07-16 09:45:00,10.51,10.58,10.5,10.58,3909.0,4116014.0 -2024-07-16 09:50:00,10.57,10.57,10.51,10.53,2082.0,2195202.0 -2024-07-16 09:55:00,10.52,10.53,10.49,10.5,1453.0,1526729.0 -2024-07-16 10:00:00,10.5,10.51,10.49,10.5,947.0,994257.0 -2024-07-16 10:05:00,10.5,10.51,10.49,10.5,946.0,993503.0 -2024-07-16 10:10:00,10.5,10.52,10.49,10.52,1514.0,1589328.0 -2024-07-16 10:15:00,10.52,10.53,10.5,10.51,619.0,650593.0 -2024-07-16 10:20:00,10.51,10.51,10.48,10.48,2161.0,2267970.0 -2024-07-16 10:25:00,10.48,10.49,10.46,10.46,1655.0,1733308.0 -2024-07-16 10:30:00,10.46,10.48,10.45,10.47,982.0,1027034.0 -2024-07-16 10:35:00,10.46,10.5,10.46,10.5,591.0,619352.0 -2024-07-16 10:40:00,10.5,10.5,10.48,10.48,738.0,774260.0 -2024-07-16 10:45:00,10.49,10.5,10.48,10.49,325.0,340925.0 -2024-07-16 10:50:00,10.5,10.51,10.49,10.5,459.0,482009.0 -2024-07-16 10:55:00,10.5,10.51,10.49,10.5,692.0,726639.0 -2024-07-16 11:00:00,10.5,10.51,10.5,10.5,107.0,112396.0 -2024-07-16 11:05:00,10.5,10.5,10.48,10.48,189.0,198371.0 -2024-07-16 11:10:00,10.48,10.49,10.47,10.47,280.0,293366.0 -2024-07-16 11:15:00,10.47,10.47,10.46,10.46,719.0,752511.0 -2024-07-16 11:20:00,10.46,10.47,10.46,10.46,323.0,337876.0 -2024-07-16 11:25:00,10.46,10.47,10.46,10.47,676.0,707383.0 -2024-07-16 11:30:00,10.46,10.48,10.46,10.48,897.0,939113.0 -2024-07-16 13:05:00,10.48,10.53,10.47,10.51,2728.0,2863349.0 -2024-07-16 13:10:00,10.51,10.54,10.5,10.53,5306.0,5585616.0 -2024-07-16 13:15:00,10.53,10.54,10.51,10.52,925.0,973819.0 -2024-07-16 13:20:00,10.53,10.53,10.5,10.51,405.0,426035.0 -2024-07-16 13:25:00,10.5,10.51,10.5,10.51,192.0,201778.0 -2024-07-16 13:30:00,10.5,10.51,10.49,10.51,614.0,644670.0 -2024-07-16 13:35:00,10.51,10.53,10.51,10.52,642.0,675225.0 -2024-07-16 13:40:00,10.53,10.53,10.51,10.53,481.0,506078.0 -2024-07-16 13:45:00,10.53,10.54,10.53,10.54,1114.0,1173596.0 -2024-07-16 13:50:00,10.54,10.54,10.52,10.52,1088.0,1145952.0 -2024-07-16 13:55:00,10.52,10.53,10.51,10.51,1119.0,1176370.0 -2024-07-16 14:00:00,10.52,10.52,10.5,10.5,2070.0,2173949.0 -2024-07-16 14:05:00,10.5,10.51,10.48,10.48,1271.0,1333599.0 -2024-07-16 14:10:00,10.48,10.49,10.46,10.46,1990.0,2085511.0 -2024-07-16 14:15:00,10.46,10.48,10.46,10.47,938.0,982201.0 -2024-07-16 14:20:00,10.47,10.48,10.46,10.47,1406.0,1472048.0 -2024-07-16 14:25:00,10.48,10.48,10.45,10.46,2145.0,2244508.0 -2024-07-16 14:30:00,10.46,10.46,10.45,10.45,1142.0,1193570.0 -2024-07-16 14:35:00,10.46,10.46,10.43,10.43,2160.0,2254821.0 -2024-07-16 14:40:00,10.43,10.44,10.42,10.43,2385.0,2486861.0 -2024-07-16 14:45:00,10.43,10.44,10.42,10.44,3285.0,3424673.0 -2024-07-16 14:50:00,10.43,10.45,10.42,10.45,2194.0,2288156.0 -2024-07-16 14:55:00,10.46,10.48,10.45,10.48,937.0,980316.0 -2024-07-16 15:00:00,10.47,10.48,10.46,10.46,904.0,946192.0 -2024-07-17 09:35:00,10.49,10.52,10.45,10.48,3110.0,3262932.0 -2024-07-17 09:40:00,10.48,10.54,10.48,10.51,5297.0,5571323.0 -2024-07-17 09:45:00,10.51,10.52,10.48,10.48,1542.0,1618979.0 -2024-07-17 09:50:00,10.48,10.48,10.46,10.47,1200.0,1256573.0 -2024-07-17 09:55:00,10.47,10.47,10.45,10.47,1463.0,1530026.0 -2024-07-17 10:00:00,10.47,10.47,10.45,10.46,763.0,798037.0 -2024-07-17 10:05:00,10.46,10.49,10.45,10.46,1703.0,1783315.0 -2024-07-17 10:10:00,10.47,10.47,10.46,10.47,192.0,200955.0 -2024-07-17 10:15:00,10.46,10.46,10.43,10.44,1858.0,1941142.0 -2024-07-17 10:20:00,10.45,10.46,10.44,10.46,349.0,364627.0 -2024-07-17 10:25:00,10.46,10.46,10.45,10.46,470.0,491561.0 -2024-07-17 10:30:00,10.47,10.48,10.46,10.48,544.0,569752.0 -2024-07-17 10:35:00,10.48,10.49,10.47,10.47,203.0,212665.0 -2024-07-17 10:40:00,10.48,10.49,10.47,10.48,486.0,509440.0 -2024-07-17 10:45:00,10.49,10.5,10.48,10.5,614.0,644302.0 -2024-07-17 10:50:00,10.5,10.5,10.48,10.49,335.0,351435.0 -2024-07-17 10:55:00,10.48,10.49,10.47,10.49,963.0,1009205.0 -2024-07-17 11:00:00,10.49,10.5,10.47,10.47,1311.0,1373486.0 -2024-07-17 11:05:00,10.48,10.48,10.47,10.47,225.0,235688.0 -2024-07-17 11:10:00,10.49,10.5,10.47,10.5,2217.0,2323890.0 -2024-07-17 11:15:00,10.49,10.52,10.49,10.51,1529.0,1605667.0 -2024-07-17 11:20:00,10.51,10.56,10.5,10.55,5555.0,5852251.0 -2024-07-17 11:25:00,10.55,10.58,10.55,10.56,2816.0,2974165.0 -2024-07-17 11:30:00,10.55,10.57,10.54,10.56,3296.0,3477444.0 -2024-07-17 13:05:00,10.56,10.56,10.54,10.55,1224.0,1291952.0 -2024-07-17 13:10:00,10.55,10.56,10.53,10.54,1813.0,1911252.0 -2024-07-17 13:15:00,10.54,10.55,10.54,10.55,536.0,565138.0 -2024-07-17 13:20:00,10.54,10.55,10.54,10.54,987.0,1040963.0 -2024-07-17 13:25:00,10.54,10.55,10.53,10.53,396.0,417059.0 -2024-07-17 13:30:00,10.52,10.54,10.52,10.52,985.0,1037275.0 -2024-07-17 13:35:00,10.53,10.55,10.52,10.54,726.0,764853.0 -2024-07-17 13:40:00,10.54,10.55,10.53,10.54,1170.0,1233424.0 -2024-07-17 13:45:00,10.53,10.54,10.53,10.54,256.0,269734.0 -2024-07-17 13:50:00,10.53,10.54,10.52,10.54,2420.0,2547211.0 -2024-07-17 13:55:00,10.54,10.55,10.53,10.53,1155.0,1217299.0 -2024-07-17 14:00:00,10.53,10.55,10.53,10.53,2078.0,2190501.0 -2024-07-17 14:05:00,10.54,10.54,10.53,10.54,2614.0,2753828.0 -2024-07-17 14:10:00,10.53,10.54,10.53,10.54,432.0,455234.0 -2024-07-17 14:15:00,10.53,10.54,10.53,10.54,1895.0,1997147.0 -2024-07-17 14:20:00,10.54,10.54,10.53,10.54,282.0,297193.0 -2024-07-17 14:25:00,10.54,10.54,10.52,10.54,887.0,934047.0 -2024-07-17 14:30:00,10.53,10.55,10.53,10.54,1787.0,1883324.0 -2024-07-17 14:35:00,10.54,10.55,10.53,10.54,1684.0,1774950.0 -2024-07-17 14:40:00,10.54,10.54,10.53,10.54,1001.0,1054331.0 -2024-07-17 14:45:00,10.54,10.54,10.53,10.53,1325.0,1395878.0 -2024-07-17 14:50:00,10.54,10.54,10.53,10.54,1330.0,1401324.0 -2024-07-17 14:55:00,10.54,10.54,10.52,10.53,2495.0,2627625.0 -2024-07-17 15:00:00,10.53,10.53,10.51,10.51,1927.0,2025513.0 -2024-07-18 09:35:00,10.53,10.53,10.42,10.45,6903.0,7230731.0 -2024-07-18 09:40:00,10.45,10.48,10.44,10.45,1520.0,1589609.0 -2024-07-18 09:45:00,10.45,10.47,10.44,10.44,1256.0,1312756.0 -2024-07-18 09:50:00,10.44,10.44,10.41,10.42,3255.0,3392651.0 -2024-07-18 09:55:00,10.42,10.42,10.37,10.41,4231.0,4396935.0 -2024-07-18 10:00:00,10.41,10.43,10.4,10.42,1199.0,1248177.0 -2024-07-18 10:05:00,10.42,10.48,10.42,10.42,2014.0,2103165.0 -2024-07-18 10:10:00,10.42,10.43,10.4,10.41,2226.0,2318149.0 -2024-07-18 10:15:00,10.41,10.43,10.4,10.41,426.0,443762.0 -2024-07-18 10:20:00,10.41,10.42,10.41,10.42,488.0,508293.0 -2024-07-18 10:25:00,10.41,10.42,10.4,10.4,1271.0,1322659.0 -2024-07-18 10:30:00,10.42,10.45,10.41,10.44,665.0,693552.0 -2024-07-18 10:35:00,10.44,10.46,10.43,10.46,1236.0,1290918.0 -2024-07-18 10:40:00,10.46,10.46,10.44,10.44,596.0,622810.0 -2024-07-18 10:45:00,10.44,10.45,10.43,10.44,202.0,210859.0 -2024-07-18 10:50:00,10.44,10.45,10.43,10.45,407.0,424662.0 -2024-07-18 10:55:00,10.44,10.45,10.43,10.45,375.0,391568.0 -2024-07-18 11:00:00,10.45,10.45,10.43,10.43,647.0,675899.0 -2024-07-18 11:05:00,10.43,10.45,10.42,10.42,431.0,449681.0 -2024-07-18 11:10:00,10.44,10.44,10.42,10.42,635.0,661931.0 -2024-07-18 11:15:00,10.42,10.43,10.41,10.42,831.0,865580.0 -2024-07-18 11:20:00,10.43,10.44,10.41,10.43,778.0,810948.0 -2024-07-18 11:25:00,10.43,10.43,10.41,10.41,758.0,789939.0 -2024-07-18 11:30:00,10.42,10.43,10.41,10.43,438.0,456320.0 -2024-07-18 13:05:00,10.42,10.44,10.41,10.44,509.0,530006.0 -2024-07-18 13:10:00,10.45,10.47,10.44,10.44,1250.0,1307347.0 -2024-07-18 13:15:00,10.45,10.5,10.45,10.5,1766.0,1850252.0 -2024-07-18 13:20:00,10.5,10.51,10.49,10.49,1228.0,1289387.0 -2024-07-18 13:25:00,10.49,10.51,10.49,10.49,702.0,736814.0 -2024-07-18 13:30:00,10.5,10.5,10.49,10.5,212.0,222532.0 -2024-07-18 13:35:00,10.5,10.53,10.5,10.53,1432.0,1506231.0 -2024-07-18 13:40:00,10.53,10.53,10.5,10.51,1031.0,1084249.0 -2024-07-18 13:45:00,10.51,10.53,10.51,10.51,1617.0,1700920.0 -2024-07-18 13:50:00,10.52,10.52,10.49,10.5,873.0,917258.0 -2024-07-18 13:55:00,10.5,10.51,10.49,10.5,857.0,900252.0 -2024-07-18 14:00:00,10.49,10.53,10.49,10.52,1077.0,1132610.0 -2024-07-18 14:05:00,10.53,10.53,10.51,10.52,363.0,381494.0 -2024-07-18 14:10:00,10.51,10.52,10.5,10.5,401.0,421394.0 -2024-07-18 14:15:00,10.5,10.52,10.5,10.51,1049.0,1102742.0 -2024-07-18 14:20:00,10.51,10.52,10.5,10.51,788.0,828183.0 -2024-07-18 14:25:00,10.52,10.52,10.5,10.52,1049.0,1102751.0 -2024-07-18 14:30:00,10.51,10.53,10.51,10.53,536.0,563965.0 -2024-07-18 14:35:00,10.53,10.53,10.52,10.52,366.0,385092.0 -2024-07-18 14:40:00,10.52,10.52,10.5,10.51,633.0,665176.0 -2024-07-18 14:45:00,10.51,10.51,10.48,10.5,912.0,956680.0 -2024-07-18 14:50:00,10.49,10.5,10.49,10.5,218.0,228788.0 -2024-07-18 14:55:00,10.49,10.52,10.49,10.52,3605.0,3787001.0 -2024-07-18 15:00:00,10.51,10.53,10.51,10.51,2779.0,2922266.0 -2024-07-19 09:35:00,10.45,10.57,10.45,10.55,6163.0,6495367.0 -2024-07-19 09:40:00,10.56,10.6,10.56,10.57,4926.0,5213031.0 -2024-07-19 09:45:00,10.58,10.59,10.55,10.55,1243.0,1313234.0 -2024-07-19 09:50:00,10.56,10.57,10.54,10.55,1337.0,1411033.0 -2024-07-19 09:55:00,10.56,10.56,10.53,10.54,1454.0,1532641.0 -2024-07-19 10:00:00,10.53,10.54,10.5,10.51,1509.0,1587040.0 -2024-07-19 10:05:00,10.52,10.52,10.49,10.51,1069.0,1122246.0 -2024-07-19 10:10:00,10.51,10.53,10.5,10.52,872.0,917109.0 -2024-07-19 10:15:00,10.53,10.54,10.52,10.52,1359.0,1431685.0 -2024-07-19 10:20:00,10.52,10.53,10.51,10.52,554.0,582810.0 -2024-07-19 10:25:00,10.52,10.52,10.51,10.52,166.0,174612.0 -2024-07-19 10:30:00,10.51,10.52,10.5,10.51,814.0,855443.0 -2024-07-19 10:35:00,10.5,10.51,10.5,10.51,605.0,635789.0 -2024-07-19 10:40:00,10.52,10.52,10.51,10.52,367.0,386021.0 -2024-07-19 10:45:00,10.52,10.54,10.52,10.54,508.0,534802.0 -2024-07-19 10:50:00,10.54,10.56,10.53,10.55,1681.0,1773511.0 -2024-07-19 10:55:00,10.54,10.56,10.54,10.56,639.0,674248.0 -2024-07-19 11:00:00,10.56,10.56,10.54,10.55,189.0,199406.0 -2024-07-19 11:05:00,10.55,10.57,10.55,10.56,731.0,771909.0 -2024-07-19 11:10:00,10.56,10.56,10.54,10.54,470.0,495855.0 -2024-07-19 11:15:00,10.55,10.56,10.55,10.56,372.0,392650.0 -2024-07-19 11:20:00,10.56,10.56,10.53,10.56,1929.0,2034934.0 -2024-07-19 11:25:00,10.56,10.57,10.56,10.56,599.0,632730.0 -2024-07-19 11:30:00,10.56,10.56,10.55,10.56,205.0,216367.0 -2024-07-19 13:05:00,10.55,10.56,10.55,10.55,1112.0,1174256.0 -2024-07-19 13:10:00,10.56,10.56,10.55,10.56,982.0,1036511.0 -2024-07-19 13:15:00,10.56,10.56,10.53,10.54,1049.0,1106121.0 -2024-07-19 13:20:00,10.53,10.56,10.53,10.55,816.0,860713.0 -2024-07-19 13:25:00,10.54,10.55,10.54,10.54,377.0,397650.0 -2024-07-19 13:30:00,10.55,10.58,10.54,10.57,3272.0,3456861.0 -2024-07-19 13:35:00,10.57,10.58,10.56,10.56,750.0,792588.0 -2024-07-19 13:40:00,10.56,10.58,10.55,10.58,679.0,717716.0 -2024-07-19 13:45:00,10.57,10.58,10.56,10.57,908.0,959813.0 -2024-07-19 13:50:00,10.57,10.57,10.55,10.56,985.0,1040036.0 -2024-07-19 13:55:00,10.55,10.57,10.55,10.56,1412.0,1490916.0 -2024-07-19 14:00:00,10.55,10.56,10.54,10.55,467.0,492673.0 -2024-07-19 14:05:00,10.54,10.56,10.54,10.55,921.0,971170.0 -2024-07-19 14:10:00,10.54,10.56,10.54,10.54,604.0,637080.0 -2024-07-19 14:15:00,10.55,10.56,10.53,10.56,1864.0,1965255.0 -2024-07-19 14:20:00,10.56,10.57,10.55,10.57,914.0,965084.0 -2024-07-19 14:25:00,10.57,10.57,10.55,10.56,627.0,662184.0 -2024-07-19 14:30:00,10.55,10.55,10.54,10.55,535.0,564260.0 -2024-07-19 14:35:00,10.55,10.56,10.55,10.56,543.0,572920.0 -2024-07-19 14:40:00,10.55,10.57,10.54,10.57,1682.0,1775952.0 -2024-07-19 14:45:00,10.56,10.57,10.55,10.57,1334.0,1408516.0 -2024-07-19 14:50:00,10.56,10.58,10.55,10.58,1592.0,1682427.0 -2024-07-19 14:55:00,10.58,10.58,10.57,10.58,2252.0,2380613.0 -2024-07-19 15:00:00,10.58,10.59,10.57,10.58,3659.0,3871778.0 -2024-07-22 09:35:00,10.57,10.6,10.52,10.54,4471.0,4718470.0 -2024-07-22 09:40:00,10.53,10.53,10.45,10.47,4986.0,5227783.0 -2024-07-22 09:45:00,10.47,10.48,10.43,10.44,3567.0,3727637.0 -2024-07-22 09:50:00,10.43,10.47,10.41,10.46,4905.0,5114770.0 -2024-07-22 09:55:00,10.46,10.46,10.45,10.45,966.0,1010351.0 -2024-07-22 10:00:00,10.46,10.49,10.46,10.46,1960.0,2053052.0 -2024-07-22 10:05:00,10.47,10.48,10.46,10.46,1000.0,1046668.0 -2024-07-22 10:10:00,10.46,10.47,10.45,10.46,666.0,696697.0 -2024-07-22 10:15:00,10.46,10.48,10.46,10.46,660.0,691030.0 -2024-07-22 10:20:00,10.47,10.49,10.46,10.47,1234.0,1292054.0 -2024-07-22 10:25:00,10.47,10.51,10.47,10.5,926.0,971762.0 -2024-07-22 10:30:00,10.5,10.52,10.49,10.52,702.0,737690.0 -2024-07-22 10:35:00,10.51,10.55,10.51,10.51,1030.0,1084519.0 -2024-07-22 10:40:00,10.51,10.52,10.5,10.51,426.0,447846.0 -2024-07-22 10:45:00,10.51,10.52,10.51,10.51,519.0,545592.0 -2024-07-22 10:50:00,10.52,10.53,10.5,10.52,765.0,804169.0 -2024-07-22 10:55:00,10.52,10.53,10.51,10.52,575.0,604815.0 -2024-07-22 11:00:00,10.53,10.53,10.51,10.53,769.0,808927.0 -2024-07-22 11:05:00,10.52,10.54,10.52,10.53,1321.0,1391018.0 -2024-07-22 11:10:00,10.53,10.55,10.53,10.53,1367.0,1440859.0 -2024-07-22 11:15:00,10.53,10.55,10.53,10.55,587.0,618390.0 -2024-07-22 11:20:00,10.53,10.54,10.52,10.54,578.0,608734.0 -2024-07-22 11:25:00,10.52,10.54,10.52,10.53,498.0,524206.0 -2024-07-22 11:30:00,10.53,10.55,10.52,10.55,2017.0,2126333.0 -2024-07-22 13:05:00,10.54,10.56,10.53,10.53,651.0,686494.0 -2024-07-22 13:10:00,10.54,10.54,10.5,10.51,1071.0,1126231.0 -2024-07-22 13:15:00,10.51,10.52,10.5,10.52,460.0,483148.0 -2024-07-22 13:20:00,10.5,10.51,10.49,10.49,446.0,468384.0 -2024-07-22 13:25:00,10.5,10.51,10.49,10.51,892.0,937056.0 -2024-07-22 13:30:00,10.51,10.51,10.49,10.5,360.0,377817.0 -2024-07-22 13:35:00,10.5,10.52,10.49,10.5,767.0,806112.0 -2024-07-22 13:40:00,10.5,10.51,10.5,10.51,234.0,245737.0 -2024-07-22 13:45:00,10.5,10.51,10.5,10.5,628.0,659641.0 -2024-07-22 13:50:00,10.51,10.51,10.49,10.5,655.0,688017.0 -2024-07-22 13:55:00,10.5,10.52,10.5,10.5,782.0,821795.0 -2024-07-22 14:00:00,10.51,10.51,10.49,10.5,1244.0,1306153.0 -2024-07-22 14:05:00,10.5,10.5,10.47,10.49,1167.0,1223545.0 -2024-07-22 14:10:00,10.49,10.49,10.48,10.49,531.0,556830.0 -2024-07-22 14:15:00,10.49,10.51,10.49,10.5,609.0,639354.0 -2024-07-22 14:20:00,10.5,10.51,10.49,10.51,920.0,965735.0 -2024-07-22 14:25:00,10.51,10.52,10.5,10.52,436.0,458320.0 -2024-07-22 14:30:00,10.51,10.52,10.5,10.51,699.0,734581.0 -2024-07-22 14:35:00,10.51,10.52,10.5,10.52,674.0,708563.0 -2024-07-22 14:40:00,10.52,10.53,10.51,10.53,957.0,1007022.0 -2024-07-22 14:45:00,10.52,10.53,10.52,10.53,520.0,547301.0 -2024-07-22 14:50:00,10.53,10.54,10.52,10.54,1638.0,1724863.0 -2024-07-22 14:55:00,10.54,10.54,10.53,10.54,895.0,942739.0 -2024-07-22 15:00:00,10.54,10.54,10.52,10.52,1958.0,2061312.0 -2024-07-23 09:35:00,10.53,10.54,10.46,10.49,2289.0,2403085.0 -2024-07-23 09:40:00,10.5,10.51,10.49,10.5,749.0,786865.0 -2024-07-23 09:45:00,10.5,10.51,10.49,10.49,742.0,778888.0 -2024-07-23 09:50:00,10.49,10.53,10.49,10.52,706.0,742465.0 -2024-07-23 09:55:00,10.52,10.52,10.49,10.5,1091.0,1145815.0 -2024-07-23 10:00:00,10.49,10.5,10.47,10.47,1447.0,1517564.0 -2024-07-23 10:05:00,10.47,10.48,10.46,10.47,1342.0,1404492.0 -2024-07-23 10:10:00,10.48,10.48,10.45,10.47,2055.0,2150373.0 -2024-07-23 10:15:00,10.45,10.47,10.45,10.46,915.0,956649.0 -2024-07-23 10:20:00,10.45,10.48,10.45,10.46,769.0,804580.0 -2024-07-23 10:25:00,10.46,10.48,10.46,10.46,362.0,379019.0 -2024-07-23 10:30:00,10.47,10.48,10.46,10.46,1094.0,1145243.0 -2024-07-23 10:35:00,10.46,10.48,10.46,10.47,755.0,790031.0 -2024-07-23 10:40:00,10.48,10.48,10.46,10.47,219.0,229316.0 -2024-07-23 10:45:00,10.47,10.48,10.45,10.45,1731.0,1810590.0 -2024-07-23 10:50:00,10.45,10.45,10.44,10.44,364.0,380098.0 -2024-07-23 10:55:00,10.44,10.45,10.42,10.43,1789.0,1865882.0 -2024-07-23 11:00:00,10.44,10.44,10.42,10.42,645.0,672903.0 -2024-07-23 11:05:00,10.43,10.44,10.42,10.44,269.0,280589.0 -2024-07-23 11:10:00,10.44,10.44,10.43,10.44,219.0,228607.0 -2024-07-23 11:15:00,10.44,10.45,10.43,10.44,350.0,365391.0 -2024-07-23 11:20:00,10.44,10.44,10.43,10.44,368.0,383900.0 -2024-07-23 11:25:00,10.43,10.44,10.39,10.4,4352.0,4528741.0 -2024-07-23 11:30:00,10.4,10.41,10.39,10.39,1428.0,1484411.0 -2024-07-23 13:05:00,10.4,10.4,10.37,10.38,1896.0,1969108.0 -2024-07-23 13:10:00,10.37,10.4,10.37,10.39,1418.0,1472554.0 -2024-07-23 13:15:00,10.39,10.4,10.38,10.39,611.0,634838.0 -2024-07-23 13:20:00,10.39,10.4,10.37,10.37,895.0,929364.0 -2024-07-23 13:25:00,10.37,10.39,10.37,10.38,1099.0,1140723.0 -2024-07-23 13:30:00,10.39,10.39,10.38,10.38,538.0,558817.0 -2024-07-23 13:35:00,10.38,10.39,10.38,10.38,335.0,347931.0 -2024-07-23 13:40:00,10.39,10.39,10.38,10.38,904.0,938891.0 -2024-07-23 13:45:00,10.38,10.39,10.38,10.38,433.0,449640.0 -2024-07-23 13:50:00,10.39,10.39,10.37,10.37,1274.0,1321579.0 -2024-07-23 13:55:00,10.38,10.38,10.36,10.37,755.0,782916.0 -2024-07-23 14:00:00,10.37,10.38,10.36,10.38,644.0,667869.0 -2024-07-23 14:05:00,10.38,10.4,10.37,10.38,938.0,973790.0 -2024-07-23 14:10:00,10.38,10.39,10.38,10.38,255.0,264928.0 -2024-07-23 14:15:00,10.38,10.39,10.37,10.37,927.0,961956.0 -2024-07-23 14:20:00,10.37,10.38,10.36,10.37,1913.0,1983527.0 -2024-07-23 14:25:00,10.37,10.37,10.36,10.36,1299.0,1346063.0 -2024-07-23 14:30:00,10.36,10.37,10.35,10.36,812.0,841359.0 -2024-07-23 14:35:00,10.37,10.37,10.33,10.33,1981.0,2050570.0 -2024-07-23 14:40:00,10.33,10.34,10.32,10.33,1072.0,1107298.0 -2024-07-23 14:45:00,10.33,10.34,10.3,10.31,2478.0,2557077.0 -2024-07-23 14:50:00,10.31,10.33,10.31,10.32,1418.0,1462794.0 -2024-07-23 14:55:00,10.32,10.32,10.28,10.28,3397.0,3498854.0 -2024-07-23 15:00:00,10.28,10.28,10.27,10.27,2799.0,2874964.0 -2024-07-24 09:35:00,10.28,10.31,10.22,10.27,4835.0,4960139.0 -2024-07-24 09:40:00,10.28,10.34,10.26,10.3,4669.0,4806575.0 -2024-07-24 09:45:00,10.3,10.35,10.26,10.26,2104.0,2169485.0 -2024-07-24 09:50:00,10.26,10.3,10.25,10.28,1331.0,1366638.0 -2024-07-24 09:55:00,10.27,10.29,10.25,10.28,2076.0,2130929.0 -2024-07-24 10:00:00,10.26,10.28,10.26,10.27,794.0,815337.0 -2024-07-24 10:05:00,10.26,10.28,10.25,10.25,834.0,855779.0 -2024-07-24 10:10:00,10.25,10.29,10.25,10.29,1481.0,1520112.0 -2024-07-24 10:15:00,10.29,10.3,10.29,10.3,765.0,787450.0 -2024-07-24 10:20:00,10.3,10.3,10.28,10.29,296.0,304554.0 -2024-07-24 10:25:00,10.29,10.29,10.26,10.27,678.0,696729.0 -2024-07-24 10:30:00,10.26,10.26,10.25,10.25,760.0,779543.0 -2024-07-24 10:35:00,10.25,10.25,10.23,10.23,790.0,808791.0 -2024-07-24 10:40:00,10.23,10.24,10.21,10.22,2667.0,2726204.0 -2024-07-24 10:45:00,10.22,10.24,10.22,10.22,886.0,906044.0 -2024-07-24 10:50:00,10.23,10.23,10.21,10.21,1281.0,1308948.0 -2024-07-24 10:55:00,10.21,10.22,10.2,10.21,2605.0,2658378.0 -2024-07-24 11:00:00,10.22,10.26,10.22,10.24,2031.0,2080133.0 -2024-07-24 11:05:00,10.23,10.27,10.23,10.26,938.0,961793.0 -2024-07-24 11:10:00,10.26,10.26,10.23,10.25,730.0,748301.0 -2024-07-24 11:15:00,10.25,10.25,10.23,10.25,381.0,390211.0 -2024-07-24 11:20:00,10.25,10.27,10.24,10.26,409.0,419803.0 -2024-07-24 11:25:00,10.28,10.28,10.26,10.26,377.0,387254.0 -2024-07-24 11:30:00,10.26,10.3,10.26,10.29,762.0,783145.0 -2024-07-24 13:05:00,10.28,10.32,10.28,10.3,1826.0,1880479.0 -2024-07-24 13:10:00,10.3,10.32,10.28,10.28,535.0,551029.0 -2024-07-24 13:15:00,10.29,10.3,10.28,10.28,419.0,431304.0 -2024-07-24 13:20:00,10.28,10.3,10.28,10.29,444.0,456696.0 -2024-07-24 13:25:00,10.28,10.3,10.27,10.27,758.0,779747.0 -2024-07-24 13:30:00,10.27,10.28,10.27,10.27,534.0,548643.0 -2024-07-24 13:35:00,10.27,10.29,10.27,10.28,1719.0,1766959.0 -2024-07-24 13:40:00,10.27,10.28,10.27,10.27,384.0,394632.0 -2024-07-24 13:45:00,10.27,10.28,10.26,10.26,803.0,824726.0 -2024-07-24 13:50:00,10.26,10.29,10.26,10.27,930.0,955590.0 -2024-07-24 13:55:00,10.26,10.27,10.26,10.27,365.0,374663.0 -2024-07-24 14:00:00,10.26,10.3,10.26,10.29,1191.0,1224104.0 -2024-07-24 14:05:00,10.3,10.3,10.27,10.28,643.0,661236.0 -2024-07-24 14:10:00,10.28,10.29,10.27,10.27,507.0,521308.0 -2024-07-24 14:15:00,10.27,10.27,10.25,10.25,638.0,654960.0 -2024-07-24 14:20:00,10.25,10.26,10.24,10.24,621.0,636337.0 -2024-07-24 14:25:00,10.24,10.25,10.24,10.24,708.0,725072.0 -2024-07-24 14:30:00,10.23,10.24,10.23,10.24,816.0,835279.0 -2024-07-24 14:35:00,10.24,10.24,10.22,10.23,773.0,790798.0 -2024-07-24 14:40:00,10.23,10.24,10.2,10.21,2472.0,2523945.0 -2024-07-24 14:45:00,10.22,10.25,10.21,10.24,1751.0,1791836.0 -2024-07-24 14:50:00,10.23,10.24,10.21,10.21,1099.0,1123861.0 -2024-07-24 14:55:00,10.22,10.23,10.2,10.2,1448.0,1478756.0 -2024-07-24 15:00:00,10.2,10.22,10.2,10.22,1297.0,1324662.0 -2024-07-25 09:35:00,10.2,10.22,10.13,10.19,3168.0,3222564.0 -2024-07-25 09:40:00,10.18,10.21,10.15,10.21,2458.0,2500748.0 -2024-07-25 09:45:00,10.2,10.24,10.19,10.19,912.0,931541.0 -2024-07-25 09:50:00,10.19,10.22,10.17,10.17,786.0,801188.0 -2024-07-25 09:55:00,10.17,10.2,10.17,10.18,1266.0,1289201.0 -2024-07-25 10:00:00,10.18,10.19,10.18,10.18,944.0,961330.0 -2024-07-25 10:05:00,10.18,10.21,10.17,10.19,950.0,968245.0 -2024-07-25 10:10:00,10.19,10.23,10.18,10.23,2199.0,2242645.0 -2024-07-25 10:15:00,10.23,10.27,10.23,10.26,1258.0,1289229.0 -2024-07-25 10:20:00,10.27,10.27,10.24,10.27,1074.0,1100921.0 -2024-07-25 10:25:00,10.26,10.29,10.26,10.26,1285.0,1320370.0 -2024-07-25 10:30:00,10.26,10.28,10.25,10.25,500.0,513354.0 -2024-07-25 10:35:00,10.25,10.27,10.25,10.25,484.0,496289.0 -2024-07-25 10:40:00,10.25,10.27,10.24,10.26,311.0,318695.0 -2024-07-25 10:45:00,10.26,10.27,10.25,10.26,971.0,994845.0 -2024-07-25 10:50:00,10.26,10.27,10.26,10.27,463.0,475271.0 -2024-07-25 10:55:00,10.27,10.33,10.26,10.3,3899.0,4011716.0 -2024-07-25 11:00:00,10.3,10.32,10.3,10.31,1391.0,1433451.0 -2024-07-25 11:05:00,10.31,10.33,10.3,10.3,1991.0,2053576.0 -2024-07-25 11:10:00,10.3,10.35,10.3,10.34,1594.0,1647117.0 -2024-07-25 11:15:00,10.35,10.36,10.34,10.36,1411.0,1460293.0 -2024-07-25 11:20:00,10.35,10.4,10.35,10.39,2372.0,2461581.0 -2024-07-25 11:25:00,10.39,10.4,10.38,10.38,1572.0,1632376.0 -2024-07-25 11:30:00,10.38,10.4,10.38,10.39,2290.0,2379362.0 -2024-07-25 13:05:00,10.39,10.4,10.37,10.38,1446.0,1501578.0 -2024-07-25 13:10:00,10.37,10.37,10.34,10.34,504.0,521826.0 -2024-07-25 13:15:00,10.35,10.35,10.33,10.34,526.0,543635.0 -2024-07-25 13:20:00,10.33,10.35,10.33,10.33,448.0,462964.0 -2024-07-25 13:25:00,10.33,10.37,10.33,10.34,1049.0,1085641.0 -2024-07-25 13:30:00,10.35,10.35,10.34,10.34,238.0,246194.0 -2024-07-25 13:35:00,10.34,10.34,10.32,10.33,647.0,668398.0 -2024-07-25 13:40:00,10.32,10.35,10.32,10.34,636.0,657495.0 -2024-07-25 13:45:00,10.34,10.34,10.32,10.33,300.0,309949.0 -2024-07-25 13:50:00,10.34,10.37,10.33,10.36,1115.0,1153825.0 -2024-07-25 13:55:00,10.36,10.37,10.35,10.35,1145.0,1186495.0 -2024-07-25 14:00:00,10.35,10.36,10.34,10.35,1484.0,1535918.0 -2024-07-25 14:05:00,10.35,10.37,10.35,10.36,657.0,680298.0 -2024-07-25 14:10:00,10.36,10.36,10.32,10.32,836.0,864211.0 -2024-07-25 14:15:00,10.33,10.33,10.27,10.3,2443.0,2516842.0 -2024-07-25 14:20:00,10.29,10.32,10.29,10.32,894.0,921421.0 -2024-07-25 14:25:00,10.32,10.33,10.32,10.33,233.0,240561.0 -2024-07-25 14:30:00,10.32,10.33,10.31,10.31,765.0,789186.0 -2024-07-25 14:35:00,10.31,10.32,10.3,10.3,578.0,595751.0 -2024-07-25 14:40:00,10.3,10.31,10.29,10.29,353.0,363590.0 -2024-07-25 14:45:00,10.3,10.32,10.29,10.31,740.0,762550.0 -2024-07-25 14:50:00,10.31,10.33,10.3,10.31,2518.0,2596719.0 -2024-07-25 14:55:00,10.31,10.32,10.3,10.31,668.0,688613.0 -2024-07-25 15:00:00,10.3,10.31,10.3,10.31,1225.0,1262682.0 -2024-07-26 09:35:00,10.29,10.33,10.29,10.33,2320.0,2391702.0 -2024-07-26 09:40:00,10.33,10.34,10.32,10.33,1189.0,1228248.0 -2024-07-26 09:45:00,10.34,10.38,10.33,10.38,1090.0,1129248.0 -2024-07-26 09:50:00,10.38,10.39,10.36,10.37,931.0,965834.0 -2024-07-26 09:55:00,10.37,10.4,10.36,10.37,2364.0,2453955.0 -2024-07-26 10:00:00,10.37,10.38,10.36,10.37,1030.0,1068430.0 -2024-07-26 10:05:00,10.37,10.38,10.35,10.36,1378.0,1428603.0 -2024-07-26 10:10:00,10.36,10.38,10.34,10.34,1069.0,1107049.0 -2024-07-26 10:15:00,10.34,10.36,10.33,10.35,581.0,600987.0 -2024-07-26 10:20:00,10.34,10.35,10.32,10.33,778.0,803529.0 -2024-07-26 10:25:00,10.34,10.34,10.32,10.33,624.0,644468.0 -2024-07-26 10:30:00,10.33,10.34,10.31,10.33,337.0,348005.0 -2024-07-26 10:35:00,10.34,10.36,10.33,10.35,848.0,877357.0 -2024-07-26 10:40:00,10.35,10.35,10.34,10.35,436.0,450998.0 -2024-07-26 10:45:00,10.35,10.36,10.35,10.35,271.0,280622.0 -2024-07-26 10:50:00,10.35,10.36,10.34,10.35,619.0,640692.0 -2024-07-26 10:55:00,10.35,10.36,10.33,10.34,396.0,409598.0 -2024-07-26 11:00:00,10.34,10.35,10.33,10.35,247.0,255551.0 -2024-07-26 11:05:00,10.35,10.37,10.34,10.37,1033.0,1069955.0 -2024-07-26 11:10:00,10.37,10.38,10.36,10.38,703.0,728998.0 -2024-07-26 11:15:00,10.38,10.4,10.37,10.39,796.0,826817.0 -2024-07-26 11:20:00,10.4,10.41,10.39,10.41,1313.0,1365586.0 -2024-07-26 11:25:00,10.41,10.41,10.38,10.39,1175.0,1222030.0 -2024-07-26 11:30:00,10.39,10.4,10.38,10.39,375.0,389553.0 -2024-07-26 13:05:00,10.39,10.4,10.36,10.38,771.0,800103.0 -2024-07-26 13:10:00,10.38,10.42,10.38,10.41,1697.0,1765280.0 -2024-07-26 13:15:00,10.41,10.41,10.39,10.39,104.0,108161.0 -2024-07-26 13:20:00,10.39,10.42,10.39,10.42,1041.0,1083617.0 -2024-07-26 13:25:00,10.42,10.46,10.42,10.45,3026.0,3160659.0 -2024-07-26 13:30:00,10.46,10.46,10.42,10.43,1186.0,1238516.0 -2024-07-26 13:35:00,10.43,10.44,10.41,10.41,331.0,345141.0 -2024-07-26 13:40:00,10.41,10.44,10.41,10.43,832.0,867992.0 -2024-07-26 13:45:00,10.42,10.43,10.4,10.42,634.0,659973.0 -2024-07-26 13:50:00,10.42,10.42,10.41,10.42,338.0,352076.0 -2024-07-26 13:55:00,10.41,10.42,10.4,10.41,627.0,652812.0 -2024-07-26 14:00:00,10.42,10.43,10.42,10.43,296.0,308170.0 -2024-07-26 14:05:00,10.42,10.42,10.4,10.41,595.0,619621.0 -2024-07-26 14:10:00,10.42,10.42,10.4,10.4,423.0,440225.0 -2024-07-26 14:15:00,10.4,10.4,10.39,10.4,719.0,747514.0 -2024-07-26 14:20:00,10.4,10.41,10.4,10.41,220.0,228829.0 -2024-07-26 14:25:00,10.4,10.41,10.39,10.4,745.0,774792.0 -2024-07-26 14:30:00,10.4,10.43,10.4,10.41,704.0,733094.0 -2024-07-26 14:35:00,10.41,10.43,10.41,10.42,378.0,393808.0 -2024-07-26 14:40:00,10.42,10.42,10.4,10.41,789.0,821777.0 -2024-07-26 14:45:00,10.4,10.42,10.4,10.42,521.0,542422.0 -2024-07-26 14:50:00,10.42,10.43,10.41,10.42,991.0,1032817.0 -2024-07-26 14:55:00,10.42,10.43,10.41,10.42,1553.0,1618226.0 -2024-07-26 15:00:00,10.42,10.43,10.42,10.43,1172.0,1222086.0 -2024-07-29 09:35:00,10.44,10.44,10.34,10.34,3854.0,4003183.0 -2024-07-29 09:40:00,10.34,10.34,10.29,10.32,3710.0,3827804.0 -2024-07-29 09:45:00,10.31,10.34,10.31,10.34,1147.0,1183964.0 -2024-07-29 09:50:00,10.33,10.35,10.31,10.35,1152.0,1191121.0 -2024-07-29 09:55:00,10.36,10.37,10.34,10.35,944.0,977541.0 -2024-07-29 10:00:00,10.36,10.37,10.33,10.33,847.0,877016.0 -2024-07-29 10:05:00,10.33,10.33,10.31,10.31,1094.0,1129000.0 -2024-07-29 10:10:00,10.31,10.36,10.31,10.35,886.0,916261.0 -2024-07-29 10:15:00,10.35,10.35,10.31,10.33,794.0,819853.0 -2024-07-29 10:20:00,10.33,10.35,10.33,10.34,447.0,462130.0 -2024-07-29 10:25:00,10.34,10.35,10.34,10.34,152.0,157215.0 -2024-07-29 10:30:00,10.35,10.35,10.33,10.34,355.0,367120.0 -2024-07-29 10:35:00,10.34,10.36,10.33,10.36,816.0,844126.0 -2024-07-29 10:40:00,10.37,10.38,10.36,10.36,526.0,545097.0 -2024-07-29 10:45:00,10.37,10.4,10.37,10.39,857.0,889862.0 -2024-07-29 10:50:00,10.39,10.42,10.39,10.41,1619.0,1684587.0 -2024-07-29 10:55:00,10.41,10.41,10.4,10.4,228.0,237312.0 -2024-07-29 11:00:00,10.41,10.42,10.4,10.41,1007.0,1048436.0 -2024-07-29 11:05:00,10.41,10.42,10.4,10.4,221.0,230123.0 -2024-07-29 11:10:00,10.4,10.4,10.38,10.39,775.0,804802.0 -2024-07-29 11:15:00,10.38,10.41,10.38,10.39,376.0,390905.0 -2024-07-29 11:20:00,10.41,10.41,10.39,10.4,510.0,530148.0 -2024-07-29 11:25:00,10.4,10.42,10.4,10.42,895.0,931752.0 -2024-07-29 11:30:00,10.41,10.42,10.41,10.42,201.0,209354.0 -2024-07-29 13:05:00,10.41,10.41,10.38,10.39,532.0,553225.0 -2024-07-29 13:10:00,10.4,10.4,10.39,10.39,156.0,162224.0 -2024-07-29 13:15:00,10.39,10.4,10.38,10.38,173.0,179733.0 -2024-07-29 13:20:00,10.38,10.39,10.38,10.38,362.0,376095.0 -2024-07-29 13:25:00,10.39,10.39,10.36,10.36,746.0,774090.0 -2024-07-29 13:30:00,10.36,10.39,10.36,10.38,632.0,655442.0 -2024-07-29 13:35:00,10.37,10.4,10.37,10.38,841.0,873036.0 -2024-07-29 13:40:00,10.38,10.38,10.37,10.38,58.0,60199.0 -2024-07-29 13:45:00,10.38,10.38,10.37,10.38,551.0,571571.0 -2024-07-29 13:50:00,10.38,10.39,10.38,10.38,750.0,778534.0 -2024-07-29 13:55:00,10.39,10.39,10.37,10.37,517.0,536732.0 -2024-07-29 14:00:00,10.37,10.38,10.36,10.37,684.0,709250.0 -2024-07-29 14:05:00,10.36,10.38,10.36,10.38,341.0,354180.0 -2024-07-29 14:10:00,10.38,10.38,10.36,10.37,384.0,397674.0 -2024-07-29 14:15:00,10.37,10.38,10.36,10.37,500.0,518250.0 -2024-07-29 14:20:00,10.37,10.38,10.36,10.38,528.0,547634.0 -2024-07-29 14:25:00,10.38,10.41,10.38,10.39,1872.0,1946896.0 -2024-07-29 14:30:00,10.39,10.4,10.39,10.39,308.0,320222.0 -2024-07-29 14:35:00,10.4,10.4,10.39,10.4,247.0,256855.0 -2024-07-29 14:40:00,10.39,10.4,10.39,10.4,853.0,886622.0 -2024-07-29 14:45:00,10.4,10.4,10.39,10.39,492.0,511371.0 -2024-07-29 14:50:00,10.4,10.4,10.38,10.39,500.0,519606.0 -2024-07-29 14:55:00,10.39,10.4,10.38,10.38,1141.0,1185204.0 -2024-07-29 15:00:00,10.38,10.39,10.37,10.37,993.0,1030268.0 -2024-07-30 09:35:00,10.37,10.4,10.33,10.36,1574.0,1631701.0 -2024-07-30 09:40:00,10.35,10.36,10.33,10.35,617.0,638176.0 -2024-07-30 09:45:00,10.34,10.35,10.33,10.35,969.0,1001796.0 -2024-07-30 09:50:00,10.35,10.39,10.35,10.38,959.0,994693.0 -2024-07-30 09:55:00,10.37,10.37,10.33,10.34,1015.0,1051652.0 -2024-07-30 10:00:00,10.33,10.34,10.31,10.31,1542.0,1592192.0 -2024-07-30 10:05:00,10.3,10.32,10.28,10.32,2493.0,2568052.0 -2024-07-30 10:10:00,10.32,10.33,10.3,10.31,2902.0,2989948.0 -2024-07-30 10:15:00,10.31,10.34,10.31,10.34,765.0,789878.0 -2024-07-30 10:20:00,10.34,10.35,10.33,10.34,176.0,181976.0 -2024-07-30 10:25:00,10.34,10.35,10.33,10.33,279.0,288484.0 -2024-07-30 10:30:00,10.33,10.36,10.33,10.33,680.0,703502.0 -2024-07-30 10:35:00,10.34,10.38,10.34,10.37,2359.0,2443172.0 -2024-07-30 10:40:00,10.36,10.38,10.35,10.38,581.0,602439.0 -2024-07-30 10:45:00,10.38,10.41,10.37,10.41,1294.0,1344757.0 -2024-07-30 10:50:00,10.41,10.44,10.39,10.4,1839.0,1915015.0 -2024-07-30 10:55:00,10.41,10.42,10.4,10.42,520.0,541477.0 -2024-07-30 11:00:00,10.41,10.42,10.39,10.41,809.0,841804.0 -2024-07-30 11:05:00,10.41,10.41,10.4,10.4,315.0,327748.0 -2024-07-30 11:10:00,10.4,10.41,10.4,10.41,152.0,158167.0 -2024-07-30 11:15:00,10.41,10.41,10.4,10.41,266.0,276732.0 -2024-07-30 11:20:00,10.41,10.41,10.39,10.39,327.0,340102.0 -2024-07-30 11:25:00,10.39,10.42,10.39,10.41,645.0,671246.0 -2024-07-30 11:30:00,10.41,10.42,10.39,10.4,474.0,493265.0 -2024-07-30 13:05:00,10.41,10.41,10.39,10.39,110.0,114376.0 -2024-07-30 13:10:00,10.4,10.4,10.37,10.37,474.0,492168.0 -2024-07-30 13:15:00,10.37,10.37,10.36,10.37,221.0,229156.0 -2024-07-30 13:20:00,10.36,10.37,10.35,10.37,327.0,338839.0 -2024-07-30 13:25:00,10.37,10.38,10.36,10.37,332.0,344283.0 -2024-07-30 13:30:00,10.37,10.38,10.37,10.37,78.0,80902.0 -2024-07-30 13:35:00,10.38,10.39,10.36,10.37,441.0,457577.0 -2024-07-30 13:40:00,10.37,10.38,10.37,10.37,108.0,112015.0 -2024-07-30 13:45:00,10.39,10.42,10.38,10.4,932.0,969059.0 -2024-07-30 13:50:00,10.4,10.4,10.38,10.38,294.0,305710.0 -2024-07-30 13:55:00,10.38,10.38,10.36,10.38,495.0,513474.0 -2024-07-30 14:00:00,10.37,10.38,10.37,10.37,89.0,92322.0 -2024-07-30 14:05:00,10.37,10.38,10.36,10.37,436.0,451957.0 -2024-07-30 14:10:00,10.38,10.38,10.36,10.36,74.0,76722.0 -2024-07-30 14:15:00,10.36,10.37,10.35,10.35,239.0,247570.0 -2024-07-30 14:20:00,10.35,10.37,10.35,10.37,522.0,540932.0 -2024-07-30 14:25:00,10.38,10.38,10.36,10.36,408.0,422954.0 -2024-07-30 14:30:00,10.37,10.37,10.36,10.36,54.0,55996.0 -2024-07-30 14:35:00,10.37,10.38,10.36,10.37,388.0,402328.0 -2024-07-30 14:40:00,10.38,10.38,10.37,10.37,738.0,765834.0 -2024-07-30 14:45:00,10.37,10.38,10.37,10.38,393.0,407607.0 -2024-07-30 14:50:00,10.38,10.38,10.37,10.37,452.0,468909.0 -2024-07-30 14:55:00,10.37,10.39,10.37,10.39,1596.0,1656756.0 -2024-07-30 15:00:00,10.39,10.39,10.37,10.38,1165.0,1209586.0 -2024-07-31 09:35:00,10.37,10.49,10.37,10.46,4769.0,4982458.0 -2024-07-31 09:40:00,10.47,10.52,10.47,10.5,4991.0,5237909.0 -2024-07-31 09:45:00,10.5,10.6,10.49,10.57,6856.0,7233100.0 -2024-07-31 09:50:00,10.57,10.61,10.56,10.59,5984.0,6331238.0 -2024-07-31 09:55:00,10.59,10.62,10.58,10.6,5142.0,5452830.0 -2024-07-31 10:00:00,10.6,10.64,10.59,10.61,3738.0,3966675.0 -2024-07-31 10:05:00,10.6,10.61,10.58,10.58,1801.0,1907277.0 -2024-07-31 10:10:00,10.58,10.6,10.58,10.6,1697.0,1797176.0 -2024-07-31 10:15:00,10.6,10.63,10.6,10.61,1780.0,1889728.0 -2024-07-31 10:20:00,10.62,10.63,10.61,10.63,1237.0,1313655.0 -2024-07-31 10:25:00,10.63,10.63,10.61,10.61,1355.0,1439525.0 -2024-07-31 10:30:00,10.61,10.62,10.59,10.6,1704.0,1807025.0 -2024-07-31 10:35:00,10.61,10.64,10.61,10.63,1472.0,1564728.0 -2024-07-31 10:40:00,10.63,10.65,10.62,10.64,1515.0,1611608.0 -2024-07-31 10:45:00,10.65,10.65,10.62,10.63,2117.0,2251622.0 -2024-07-31 10:50:00,10.63,10.64,10.63,10.63,1036.0,1101733.0 -2024-07-31 10:55:00,10.64,10.64,10.63,10.64,934.0,993451.0 -2024-07-31 11:00:00,10.64,10.66,10.63,10.66,1630.0,1735747.0 -2024-07-31 11:05:00,10.66,10.67,10.65,10.66,1342.0,1430692.0 -2024-07-31 11:10:00,10.66,10.66,10.64,10.65,580.0,617827.0 -2024-07-31 11:15:00,10.65,10.66,10.64,10.64,695.0,740393.0 -2024-07-31 11:20:00,10.65,10.67,10.64,10.67,993.0,1058547.0 -2024-07-31 11:25:00,10.67,10.69,10.65,10.69,2134.0,2277288.0 -2024-07-31 11:30:00,10.69,10.7,10.67,10.69,1374.0,1468191.0 -2024-07-31 13:05:00,10.69,10.71,10.67,10.7,5171.0,5525590.0 -2024-07-31 13:10:00,10.7,10.71,10.68,10.68,1718.0,1837401.0 -2024-07-31 13:15:00,10.69,10.72,10.68,10.71,2408.0,2577143.0 -2024-07-31 13:20:00,10.72,10.75,10.71,10.73,2636.0,2829322.0 -2024-07-31 13:25:00,10.73,10.75,10.72,10.73,2417.0,2594630.0 -2024-07-31 13:30:00,10.73,10.75,10.73,10.73,1478.0,1586859.0 -2024-07-31 13:35:00,10.73,10.74,10.7,10.7,1952.0,2091734.0 -2024-07-31 13:40:00,10.7,10.71,10.69,10.7,804.0,860136.0 -2024-07-31 13:45:00,10.7,10.71,10.69,10.7,631.0,675299.0 -2024-07-31 13:50:00,10.7,10.72,10.7,10.72,1240.0,1328562.0 -2024-07-31 13:55:00,10.73,10.74,10.72,10.74,2214.0,2376301.0 -2024-07-31 14:00:00,10.74,10.74,10.72,10.73,456.0,489311.0 -2024-07-31 14:05:00,10.72,10.73,10.71,10.72,1022.0,1095574.0 -2024-07-31 14:10:00,10.71,10.73,10.71,10.72,480.0,514482.0 -2024-07-31 14:15:00,10.72,10.73,10.72,10.73,488.0,523203.0 -2024-07-31 14:20:00,10.72,10.73,10.71,10.72,669.0,717101.0 -2024-07-31 14:25:00,10.72,10.72,10.71,10.72,693.0,742664.0 -2024-07-31 14:30:00,10.72,10.72,10.7,10.72,890.0,952913.0 -2024-07-31 14:35:00,10.72,10.73,10.72,10.72,970.0,1039970.0 -2024-07-31 14:40:00,10.73,10.74,10.72,10.74,2730.0,2930120.0 -2024-07-31 14:45:00,10.74,10.74,10.72,10.74,2271.0,2438008.0 -2024-07-31 14:50:00,10.74,10.74,10.72,10.74,2161.0,2319775.0 -2024-07-31 14:55:00,10.74,10.75,10.73,10.74,3865.0,4149381.0 -2024-07-31 15:00:00,10.74,10.74,10.73,10.74,2912.0,3126952.0 -2024-08-01 09:35:00,10.74,10.82,10.72,10.77,7529.0,8108541.0 -2024-08-01 09:40:00,10.77,10.77,10.73,10.73,1920.0,2063299.0 -2024-08-01 09:45:00,10.73,10.75,10.71,10.71,2291.0,2457718.0 -2024-08-01 09:50:00,10.72,10.74,10.69,10.7,2613.0,2799686.0 -2024-08-01 09:55:00,10.71,10.71,10.68,10.7,1429.0,1528418.0 -2024-08-01 10:00:00,10.69,10.73,10.68,10.71,1557.0,1666869.0 -2024-08-01 10:05:00,10.71,10.73,10.69,10.7,1218.0,1304031.0 -2024-08-01 10:10:00,10.71,10.72,10.69,10.7,721.0,772034.0 -2024-08-01 10:15:00,10.7,10.72,10.7,10.71,843.0,902609.0 -2024-08-01 10:20:00,10.7,10.72,10.7,10.72,327.0,350141.0 -2024-08-01 10:25:00,10.72,10.73,10.71,10.72,729.0,781471.0 -2024-08-01 10:30:00,10.71,10.73,10.69,10.7,1229.0,1316175.0 -2024-08-01 10:35:00,10.7,10.7,10.68,10.7,909.0,971667.0 -2024-08-01 10:40:00,10.7,10.7,10.69,10.69,482.0,515489.0 -2024-08-01 10:45:00,10.69,10.71,10.69,10.71,524.0,560770.0 -2024-08-01 10:50:00,10.71,10.71,10.69,10.69,554.0,592940.0 -2024-08-01 10:55:00,10.71,10.71,10.68,10.68,773.0,826247.0 -2024-08-01 11:00:00,10.68,10.69,10.67,10.68,834.0,890613.0 -2024-08-01 11:05:00,10.68,10.69,10.66,10.68,1525.0,1627421.0 -2024-08-01 11:10:00,10.68,10.69,10.67,10.68,500.0,533838.0 -2024-08-01 11:15:00,10.68,10.68,10.66,10.67,460.0,490876.0 -2024-08-01 11:20:00,10.67,10.69,10.66,10.68,1415.0,1509637.0 -2024-08-01 11:25:00,10.66,10.68,10.66,10.68,733.0,781649.0 -2024-08-01 11:30:00,10.68,10.7,10.67,10.68,1009.0,1077881.0 -2024-08-01 13:05:00,10.7,10.71,10.68,10.7,455.0,486340.0 -2024-08-01 13:10:00,10.71,10.73,10.71,10.72,821.0,879934.0 -2024-08-01 13:15:00,10.73,10.75,10.72,10.73,2328.0,2499265.0 -2024-08-01 13:20:00,10.74,10.75,10.73,10.73,679.0,728793.0 -2024-08-01 13:25:00,10.73,10.74,10.73,10.74,631.0,677361.0 -2024-08-01 13:30:00,10.74,10.75,10.73,10.73,513.0,550899.0 -2024-08-01 13:35:00,10.73,10.74,10.73,10.73,238.0,255379.0 -2024-08-01 13:40:00,10.73,10.74,10.73,10.73,653.0,700717.0 -2024-08-01 13:45:00,10.73,10.74,10.73,10.73,477.0,512018.0 -2024-08-01 13:50:00,10.74,10.74,10.71,10.73,839.0,899823.0 -2024-08-01 13:55:00,10.72,10.75,10.72,10.74,1317.0,1414292.0 -2024-08-01 14:00:00,10.74,10.74,10.73,10.74,335.0,359566.0 -2024-08-01 14:05:00,10.74,10.74,10.7,10.7,1496.0,1603366.0 -2024-08-01 14:10:00,10.71,10.72,10.7,10.7,624.0,668189.0 -2024-08-01 14:15:00,10.71,10.71,10.7,10.71,243.0,260094.0 -2024-08-01 14:20:00,10.71,10.71,10.7,10.7,275.0,294276.0 -2024-08-01 14:25:00,10.7,10.72,10.7,10.71,898.0,961729.0 -2024-08-01 14:30:00,10.71,10.72,10.7,10.7,1071.0,1146554.0 -2024-08-01 14:35:00,10.71,10.72,10.7,10.7,648.0,693897.0 -2024-08-01 14:40:00,10.7,10.71,10.7,10.7,276.0,295369.0 -2024-08-01 14:45:00,10.71,10.71,10.69,10.69,799.0,855012.0 -2024-08-01 14:50:00,10.71,10.71,10.7,10.71,704.0,753602.0 -2024-08-01 14:55:00,10.71,10.71,10.7,10.71,728.0,779331.0 -2024-08-01 15:00:00,10.7,10.72,10.7,10.7,1044.0,1117644.0 -2024-08-02 09:35:00,10.67,10.72,10.63,10.71,4585.0,4899332.0 -2024-08-02 09:40:00,10.7,10.75,10.67,10.72,2819.0,3018534.0 -2024-08-02 09:45:00,10.72,10.75,10.71,10.74,1794.0,1925603.0 -2024-08-02 09:50:00,10.74,10.77,10.73,10.73,2331.0,2506990.0 -2024-08-02 09:55:00,10.73,10.77,10.73,10.76,1878.0,2019187.0 -2024-08-02 10:00:00,10.76,10.77,10.75,10.75,1081.0,1162979.0 -2024-08-02 10:05:00,10.76,10.77,10.73,10.77,1507.0,1620501.0 -2024-08-02 10:10:00,10.77,10.77,10.75,10.75,1223.0,1315129.0 -2024-08-02 10:15:00,10.76,10.76,10.74,10.74,1562.0,1677792.0 -2024-08-02 10:20:00,10.75,10.78,10.74,10.78,3135.0,3375362.0 -2024-08-02 10:25:00,10.77,10.78,10.75,10.75,567.0,610466.0 -2024-08-02 10:30:00,10.75,10.76,10.73,10.75,1532.0,1644738.0 -2024-08-02 10:35:00,10.75,10.76,10.73,10.74,928.0,997338.0 -2024-08-02 10:40:00,10.74,10.74,10.71,10.73,1005.0,1077919.0 -2024-08-02 10:45:00,10.74,10.74,10.72,10.73,386.0,414278.0 -2024-08-02 10:50:00,10.73,10.73,10.71,10.71,1545.0,1655816.0 -2024-08-02 10:55:00,10.72,10.73,10.69,10.69,725.0,776086.0 -2024-08-02 11:00:00,10.7,10.71,10.69,10.71,282.0,301779.0 -2024-08-02 11:05:00,10.71,10.72,10.69,10.72,1036.0,1109267.0 -2024-08-02 11:10:00,10.71,10.73,10.71,10.73,786.0,842591.0 -2024-08-02 11:15:00,10.73,10.74,10.72,10.73,423.0,453916.0 -2024-08-02 11:20:00,10.73,10.75,10.72,10.75,663.0,711800.0 -2024-08-02 11:25:00,10.74,10.74,10.72,10.73,557.0,597658.0 -2024-08-02 11:30:00,10.73,10.74,10.72,10.74,248.0,266097.0 -2024-08-02 13:05:00,10.74,10.76,10.73,10.76,1040.0,1117676.0 -2024-08-02 13:10:00,10.76,10.78,10.75,10.76,2050.0,2206629.0 -2024-08-02 13:15:00,10.76,10.78,10.76,10.78,1360.0,1464827.0 -2024-08-02 13:20:00,10.78,10.78,10.73,10.73,769.0,828121.0 -2024-08-02 13:25:00,10.74,10.75,10.73,10.74,389.0,417727.0 -2024-08-02 13:30:00,10.74,10.74,10.7,10.71,1664.0,1783735.0 -2024-08-02 13:35:00,10.71,10.72,10.7,10.71,440.0,471085.0 -2024-08-02 13:40:00,10.71,10.72,10.7,10.72,467.0,500167.0 -2024-08-02 13:45:00,10.72,10.74,10.72,10.72,1074.0,1152297.0 -2024-08-02 13:50:00,10.72,10.73,10.7,10.71,680.0,728569.0 -2024-08-02 13:55:00,10.71,10.72,10.69,10.69,1380.0,1477234.0 -2024-08-02 14:00:00,10.69,10.7,10.68,10.69,1076.0,1150237.0 -2024-08-02 14:05:00,10.69,10.7,10.68,10.69,596.0,637139.0 -2024-08-02 14:10:00,10.69,10.69,10.67,10.68,1057.0,1128842.0 -2024-08-02 14:15:00,10.68,10.68,10.66,10.66,734.0,783046.0 -2024-08-02 14:20:00,10.66,10.67,10.64,10.66,1214.0,1293599.0 -2024-08-02 14:25:00,10.66,10.68,10.66,10.68,699.0,745750.0 -2024-08-02 14:30:00,10.66,10.68,10.66,10.68,372.0,396951.0 -2024-08-02 14:35:00,10.68,10.68,10.65,10.65,798.0,851389.0 -2024-08-02 14:40:00,10.65,10.66,10.64,10.65,835.0,889173.0 -2024-08-02 14:45:00,10.65,10.66,10.64,10.66,1468.0,1562840.0 -2024-08-02 14:50:00,10.66,10.68,10.65,10.68,854.0,910349.0 -2024-08-02 14:55:00,10.66,10.68,10.65,10.67,1182.0,1259981.0 -2024-08-02 15:00:00,10.65,10.67,10.64,10.64,2722.0,2897627.0 -2024-08-05 09:35:00,10.59,10.77,10.57,10.75,8525.0,9119507.0 -2024-08-05 09:40:00,10.76,10.82,10.76,10.81,4463.0,4812048.0 -2024-08-05 09:45:00,10.81,10.86,10.8,10.83,6369.0,6897333.0 -2024-08-05 09:50:00,10.84,10.94,10.83,10.92,10184.0,11084367.0 -2024-08-05 09:55:00,10.92,10.93,10.86,10.86,4322.0,4706626.0 -2024-08-05 10:00:00,10.86,10.86,10.83,10.83,2051.0,2223008.0 -2024-08-05 10:05:00,10.84,10.84,10.77,10.79,2195.0,2371267.0 -2024-08-05 10:10:00,10.8,10.82,10.78,10.78,1843.0,1989085.0 -2024-08-05 10:15:00,10.78,10.78,10.76,10.77,1403.0,1511923.0 -2024-08-05 10:20:00,10.78,10.82,10.78,10.78,1243.0,1342701.0 -2024-08-05 10:25:00,10.78,10.81,10.77,10.79,1534.0,1654306.0 -2024-08-05 10:30:00,10.8,10.85,10.79,10.83,1168.0,1263744.0 -2024-08-05 10:35:00,10.84,10.84,10.8,10.8,1149.0,1243426.0 -2024-08-05 10:40:00,10.8,10.81,10.8,10.8,223.0,240958.0 -2024-08-05 10:45:00,10.79,10.83,10.79,10.82,2498.0,2697672.0 -2024-08-05 10:50:00,10.82,10.83,10.8,10.83,678.0,733057.0 -2024-08-05 10:55:00,10.83,10.86,10.82,10.84,1195.0,1296055.0 -2024-08-05 11:00:00,10.84,10.84,10.81,10.82,945.0,1023635.0 -2024-08-05 11:05:00,10.82,10.84,10.82,10.83,550.0,595778.0 -2024-08-05 11:10:00,10.83,10.84,10.81,10.83,275.0,297729.0 -2024-08-05 11:15:00,10.83,10.87,10.83,10.84,2960.0,3211333.0 -2024-08-05 11:20:00,10.84,10.85,10.84,10.85,682.0,739696.0 -2024-08-05 11:25:00,10.85,10.87,10.85,10.86,1314.0,1426553.0 -2024-08-05 11:30:00,10.86,10.87,10.86,10.87,698.0,758575.0 -2024-08-05 13:05:00,10.87,10.87,10.8,10.83,1975.0,2140390.0 -2024-08-05 13:10:00,10.82,10.82,10.77,10.77,1377.0,1486835.0 -2024-08-05 13:15:00,10.77,10.78,10.77,10.78,1069.0,1151360.0 -2024-08-05 13:20:00,10.78,10.78,10.74,10.74,2305.0,2479766.0 -2024-08-05 13:25:00,10.75,10.75,10.73,10.74,1181.0,1268215.0 -2024-08-05 13:30:00,10.74,10.75,10.73,10.74,810.0,870000.0 -2024-08-05 13:35:00,10.73,10.74,10.69,10.69,1429.0,1531073.0 -2024-08-05 13:40:00,10.69,10.72,10.66,10.69,1798.0,1920712.0 -2024-08-05 13:45:00,10.7,10.72,10.68,10.69,793.0,848511.0 -2024-08-05 13:50:00,10.69,10.7,10.68,10.68,1573.0,1681313.0 -2024-08-05 13:55:00,10.68,10.69,10.66,10.68,1547.0,1650985.0 -2024-08-05 14:00:00,10.69,10.69,10.63,10.63,1700.0,1809842.0 -2024-08-05 14:05:00,10.64,10.67,10.62,10.65,1478.0,1572992.0 -2024-08-05 14:10:00,10.65,10.68,10.65,10.66,577.0,615183.0 -2024-08-05 14:15:00,10.66,10.66,10.62,10.63,1282.0,1363308.0 -2024-08-05 14:20:00,10.64,10.68,10.63,10.68,1035.0,1102397.0 -2024-08-05 14:25:00,10.68,10.68,10.65,10.66,597.0,636236.0 -2024-08-05 14:30:00,10.66,10.67,10.64,10.65,1782.0,1898593.0 -2024-08-05 14:35:00,10.65,10.68,10.65,10.68,1273.0,1356550.0 -2024-08-05 14:40:00,10.68,10.68,10.65,10.67,978.0,1043306.0 -2024-08-05 14:45:00,10.68,10.7,10.66,10.67,980.0,1045683.0 -2024-08-05 14:50:00,10.66,10.68,10.66,10.68,974.0,1039330.0 -2024-08-05 14:55:00,10.67,10.68,10.64,10.65,1842.0,1963252.0 -2024-08-05 15:00:00,10.64,10.65,10.64,10.64,1924.0,2047554.0 -2024-08-06 09:35:00,10.7,10.78,10.7,10.71,5472.0,5875415.0 -2024-08-06 09:40:00,10.71,10.73,10.7,10.71,3524.0,3776819.0 -2024-08-06 09:45:00,10.72,10.79,10.71,10.78,2591.0,2784419.0 -2024-08-06 09:50:00,10.78,10.78,10.74,10.76,1398.0,1504073.0 -2024-08-06 09:55:00,10.76,10.84,10.75,10.82,3828.0,4134812.0 -2024-08-06 10:00:00,10.82,10.85,10.82,10.82,2497.0,2704744.0 -2024-08-06 10:05:00,10.82,10.83,10.76,10.77,3786.0,4086059.0 -2024-08-06 10:10:00,10.76,10.78,10.75,10.76,2754.0,2964167.0 -2024-08-06 10:15:00,10.76,10.77,10.74,10.74,1320.0,1419944.0 -2024-08-06 10:20:00,10.74,10.75,10.72,10.73,1146.0,1230462.0 -2024-08-06 10:25:00,10.74,10.75,10.73,10.75,423.0,454365.0 -2024-08-06 10:30:00,10.75,10.77,10.74,10.76,1038.0,1116867.0 -2024-08-06 10:35:00,10.76,10.77,10.75,10.76,1216.0,1308332.0 -2024-08-06 10:40:00,10.77,10.77,10.75,10.76,789.0,848915.0 -2024-08-06 10:45:00,10.76,10.76,10.74,10.74,478.0,513689.0 -2024-08-06 10:50:00,10.74,10.76,10.74,10.76,533.0,572856.0 -2024-08-06 10:55:00,10.76,10.76,10.75,10.76,385.0,414174.0 -2024-08-06 11:00:00,10.76,10.79,10.76,10.78,1266.0,1363947.0 -2024-08-06 11:05:00,10.78,10.81,10.78,10.79,1141.0,1231716.0 -2024-08-06 11:10:00,10.8,10.82,10.8,10.8,837.0,904416.0 -2024-08-06 11:15:00,10.8,10.81,10.79,10.79,930.0,1004559.0 -2024-08-06 11:20:00,10.8,10.82,10.79,10.81,1403.0,1516033.0 -2024-08-06 11:25:00,10.8,10.81,10.79,10.79,406.0,438195.0 -2024-08-06 11:30:00,10.79,10.8,10.78,10.79,443.0,477967.0 -2024-08-06 13:05:00,10.79,10.79,10.76,10.78,605.0,651923.0 -2024-08-06 13:10:00,10.78,10.79,10.74,10.74,1761.0,1896340.0 -2024-08-06 13:15:00,10.75,10.75,10.74,10.75,364.0,391204.0 -2024-08-06 13:20:00,10.75,10.77,10.74,10.77,496.0,533279.0 -2024-08-06 13:25:00,10.77,10.81,10.76,10.81,1960.0,2114239.0 -2024-08-06 13:30:00,10.8,10.82,10.79,10.82,1977.0,2137582.0 -2024-08-06 13:35:00,10.82,10.82,10.78,10.8,2702.0,2917856.0 -2024-08-06 13:40:00,10.81,10.82,10.8,10.81,1823.0,1971064.0 -2024-08-06 13:45:00,10.82,10.82,10.81,10.82,1051.0,1136626.0 -2024-08-06 13:50:00,10.82,10.82,10.79,10.81,1433.0,1549230.0 -2024-08-06 13:55:00,10.79,10.79,10.77,10.77,719.0,774917.0 -2024-08-06 14:00:00,10.77,10.79,10.77,10.78,1033.0,1113748.0 -2024-08-06 14:05:00,10.78,10.8,10.78,10.79,555.0,598945.0 -2024-08-06 14:10:00,10.8,10.8,10.79,10.8,329.0,355273.0 -2024-08-06 14:15:00,10.8,10.81,10.8,10.8,678.0,732441.0 -2024-08-06 14:20:00,10.81,10.81,10.8,10.8,681.0,735628.0 -2024-08-06 14:25:00,10.79,10.81,10.79,10.8,1254.0,1354221.0 -2024-08-06 14:30:00,10.8,10.83,10.8,10.81,2052.0,2219252.0 -2024-08-06 14:35:00,10.81,10.84,10.81,10.84,1802.0,1951728.0 -2024-08-06 14:40:00,10.84,10.85,10.84,10.84,2227.0,2414687.0 -2024-08-06 14:45:00,10.85,10.87,10.84,10.85,2595.0,2816150.0 -2024-08-06 14:50:00,10.86,10.86,10.84,10.86,1470.0,1595403.0 -2024-08-06 14:55:00,10.86,10.86,10.85,10.86,1892.0,2054267.0 -2024-08-06 15:00:00,10.85,10.87,10.85,10.87,3313.0,3599202.0 -2024-08-07 09:35:00,10.88,10.89,10.77,10.82,3185.0,3440831.0 -2024-08-07 09:40:00,10.82,10.86,10.78,10.78,2234.0,2415783.0 -2024-08-07 09:45:00,10.78,10.81,10.77,10.8,2851.0,3075594.0 -2024-08-07 09:50:00,10.82,10.85,10.8,10.83,1880.0,2034531.0 -2024-08-07 09:55:00,10.83,10.83,10.8,10.83,1247.0,1348582.0 -2024-08-07 10:00:00,10.82,10.82,10.78,10.79,1604.0,1731782.0 -2024-08-07 10:05:00,10.8,10.8,10.79,10.79,719.0,775993.0 -2024-08-07 10:10:00,10.8,10.8,10.76,10.78,1773.0,1910241.0 -2024-08-07 10:15:00,10.78,10.79,10.77,10.79,809.0,872124.0 -2024-08-07 10:20:00,10.79,10.8,10.78,10.79,416.0,448807.0 -2024-08-07 10:25:00,10.79,10.79,10.78,10.79,161.0,173670.0 -2024-08-07 10:30:00,10.79,10.79,10.77,10.77,588.0,634174.0 -2024-08-07 10:35:00,10.77,10.79,10.76,10.76,506.0,545060.0 -2024-08-07 10:40:00,10.76,10.78,10.75,10.78,1903.0,2048647.0 -2024-08-07 10:45:00,10.78,10.78,10.76,10.77,943.0,1015553.0 -2024-08-07 10:50:00,10.77,10.79,10.77,10.78,658.0,708972.0 -2024-08-07 10:55:00,10.78,10.79,10.77,10.78,293.0,315845.0 -2024-08-07 11:00:00,10.78,10.79,10.77,10.79,283.0,305269.0 -2024-08-07 11:05:00,10.78,10.79,10.77,10.77,381.0,410708.0 -2024-08-07 11:10:00,10.77,10.78,10.76,10.76,1110.0,1195766.0 -2024-08-07 11:15:00,10.76,10.77,10.75,10.75,1054.0,1133595.0 -2024-08-07 11:20:00,10.75,10.76,10.72,10.74,2607.0,2797323.0 -2024-08-07 11:25:00,10.73,10.76,10.73,10.75,893.0,959632.0 -2024-08-07 11:30:00,10.75,10.75,10.74,10.74,306.0,328665.0 -2024-08-07 13:05:00,10.74,10.76,10.74,10.76,538.0,578298.0 -2024-08-07 13:10:00,10.75,10.77,10.75,10.76,251.0,270083.0 -2024-08-07 13:15:00,10.76,10.77,10.76,10.77,340.0,365858.0 -2024-08-07 13:20:00,10.76,10.79,10.76,10.79,675.0,727271.0 -2024-08-07 13:25:00,10.79,10.8,10.77,10.79,1071.0,1154993.0 -2024-08-07 13:30:00,10.79,10.79,10.78,10.78,67.0,72249.0 -2024-08-07 13:35:00,10.79,10.81,10.78,10.79,744.0,803095.0 -2024-08-07 13:40:00,10.8,10.8,10.78,10.78,711.0,767128.0 -2024-08-07 13:45:00,10.78,10.78,10.76,10.76,373.0,401806.0 -2024-08-07 13:50:00,10.76,10.77,10.76,10.77,523.0,562994.0 -2024-08-07 13:55:00,10.77,10.78,10.76,10.76,1148.0,1236354.0 -2024-08-07 14:00:00,10.76,10.77,10.75,10.76,648.0,697307.0 -2024-08-07 14:05:00,10.77,10.77,10.75,10.75,285.0,306584.0 -2024-08-07 14:10:00,10.76,10.77,10.74,10.74,1156.0,1242804.0 -2024-08-07 14:15:00,10.74,10.75,10.73,10.74,1077.0,1156306.0 -2024-08-07 14:20:00,10.73,10.74,10.73,10.73,833.0,894252.0 -2024-08-07 14:25:00,10.74,10.74,10.73,10.74,525.0,563687.0 -2024-08-07 14:30:00,10.74,10.75,10.73,10.75,969.0,1040476.0 -2024-08-07 14:35:00,10.76,10.76,10.73,10.73,744.0,799035.0 -2024-08-07 14:40:00,10.74,10.74,10.72,10.73,807.0,865759.0 -2024-08-07 14:45:00,10.73,10.74,10.71,10.71,2336.0,2504013.0 -2024-08-07 14:50:00,10.71,10.74,10.71,10.74,835.0,895682.0 -2024-08-07 14:55:00,10.73,10.74,10.72,10.73,1336.0,1433003.0 -2024-08-07 15:00:00,10.74,10.74,10.71,10.71,1884.0,2019683.0 -2024-08-08 09:35:00,10.74,10.75,10.7,10.74,2684.0,2877392.0 -2024-08-08 09:40:00,10.74,10.75,10.71,10.71,2203.0,2363399.0 -2024-08-08 09:45:00,10.7,10.71,10.68,10.7,1546.0,1653859.0 -2024-08-08 09:50:00,10.7,10.71,10.68,10.7,1108.0,1184773.0 -2024-08-08 09:55:00,10.69,10.71,10.68,10.69,534.0,571025.0 -2024-08-08 10:00:00,10.69,10.72,10.69,10.7,1167.0,1249488.0 -2024-08-08 10:05:00,10.69,10.69,10.66,10.66,1685.0,1798454.0 -2024-08-08 10:10:00,10.67,10.68,10.65,10.67,887.0,946154.0 -2024-08-08 10:15:00,10.68,10.69,10.65,10.65,1371.0,1462231.0 -2024-08-08 10:20:00,10.66,10.68,10.65,10.67,467.0,497969.0 -2024-08-08 10:25:00,10.67,10.68,10.66,10.66,923.0,984344.0 -2024-08-08 10:30:00,10.66,10.68,10.66,10.67,526.0,561056.0 -2024-08-08 10:35:00,10.66,10.71,10.66,10.7,1209.0,1292509.0 -2024-08-08 10:40:00,10.7,10.78,10.7,10.77,2802.0,3009779.0 -2024-08-08 10:45:00,10.77,10.84,10.76,10.79,5584.0,6038441.0 -2024-08-08 10:50:00,10.8,10.82,10.78,10.8,3043.0,3287230.0 -2024-08-08 10:55:00,10.79,10.81,10.77,10.8,1226.0,1323931.0 -2024-08-08 11:00:00,10.81,10.82,10.8,10.82,1534.0,1659179.0 -2024-08-08 11:05:00,10.83,10.84,10.8,10.81,1750.0,1893980.0 -2024-08-08 11:10:00,10.81,10.86,10.81,10.82,2621.0,2841688.0 -2024-08-08 11:15:00,10.82,10.86,10.82,10.86,1712.0,1856989.0 -2024-08-08 11:20:00,10.86,10.87,10.83,10.86,1694.0,1838329.0 -2024-08-08 11:25:00,10.86,10.87,10.84,10.86,937.0,1017298.0 -2024-08-08 11:30:00,10.85,10.87,10.85,10.86,1086.0,1179460.0 -2024-08-08 13:05:00,10.87,10.9,10.84,10.84,4134.0,4496565.0 -2024-08-08 13:10:00,10.83,10.85,10.82,10.85,713.0,772596.0 -2024-08-08 13:15:00,10.85,10.86,10.84,10.84,288.0,312409.0 -2024-08-08 13:20:00,10.85,10.85,10.83,10.83,548.0,593300.0 -2024-08-08 13:25:00,10.83,10.87,10.82,10.85,1264.0,1371021.0 -2024-08-08 13:30:00,10.85,10.86,10.85,10.85,397.0,430817.0 -2024-08-08 13:35:00,10.85,10.86,10.83,10.86,1776.0,1927884.0 -2024-08-08 13:40:00,10.84,10.84,10.82,10.83,426.0,461616.0 -2024-08-08 13:45:00,10.83,10.84,10.82,10.83,520.0,563461.0 -2024-08-08 13:50:00,10.83,10.87,10.83,10.87,3778.0,4099148.0 -2024-08-08 13:55:00,10.87,10.88,10.85,10.87,991.0,1077025.0 -2024-08-08 14:00:00,10.87,10.87,10.85,10.85,340.0,369199.0 -2024-08-08 14:05:00,10.86,10.87,10.84,10.84,813.0,882466.0 -2024-08-08 14:10:00,10.84,10.85,10.84,10.84,244.0,264513.0 -2024-08-08 14:15:00,10.85,10.88,10.85,10.86,1563.0,1698365.0 -2024-08-08 14:20:00,10.86,10.87,10.85,10.86,484.0,525397.0 -2024-08-08 14:25:00,10.86,10.86,10.85,10.85,543.0,589319.0 -2024-08-08 14:30:00,10.85,10.86,10.84,10.85,573.0,621609.0 -2024-08-08 14:35:00,10.86,10.86,10.84,10.85,381.0,413423.0 -2024-08-08 14:40:00,10.86,10.86,10.84,10.86,440.0,477558.0 -2024-08-08 14:45:00,10.85,10.86,10.84,10.85,581.0,630158.0 -2024-08-08 14:50:00,10.84,10.85,10.83,10.85,951.0,1030978.0 -2024-08-08 14:55:00,10.85,10.85,10.84,10.84,1195.0,1296184.0 -2024-08-08 15:00:00,10.84,10.85,10.84,10.84,1523.0,1651033.0 -2024-08-09 09:35:00,10.85,10.87,10.77,10.79,5844.0,6316928.0 -2024-08-09 09:40:00,10.79,10.82,10.78,10.81,2381.0,2571795.0 -2024-08-09 09:45:00,10.8,10.81,10.79,10.8,1960.0,2115520.0 -2024-08-09 09:50:00,10.81,10.84,10.8,10.83,1728.0,1869057.0 -2024-08-09 09:55:00,10.83,10.83,10.8,10.81,727.0,786482.0 -2024-08-09 10:00:00,10.81,10.82,10.8,10.8,756.0,816832.0 -2024-08-09 10:05:00,10.8,10.81,10.79,10.8,859.0,927208.0 -2024-08-09 10:10:00,10.79,10.81,10.79,10.8,200.0,216008.0 -2024-08-09 10:15:00,10.8,10.82,10.8,10.81,363.0,392281.0 -2024-08-09 10:20:00,10.8,10.8,10.78,10.79,1167.0,1259260.0 -2024-08-09 10:25:00,10.78,10.78,10.73,10.74,4217.0,4536883.0 -2024-08-09 10:30:00,10.76,10.77,10.75,10.76,130.0,139892.0 -2024-08-09 10:35:00,10.76,10.78,10.75,10.77,1450.0,1560025.0 -2024-08-09 10:40:00,10.78,10.78,10.77,10.77,214.0,230505.0 -2024-08-09 10:45:00,10.77,10.79,10.77,10.79,293.0,315780.0 -2024-08-09 10:50:00,10.79,10.8,10.78,10.78,875.0,943927.0 -2024-08-09 10:55:00,10.78,10.79,10.77,10.78,595.0,641230.0 -2024-08-09 11:00:00,10.78,10.79,10.75,10.76,1246.0,1341539.0 -2024-08-09 11:05:00,10.76,10.76,10.74,10.75,1533.0,1647200.0 -2024-08-09 11:10:00,10.75,10.76,10.74,10.76,473.0,508338.0 -2024-08-09 11:15:00,10.75,10.76,10.75,10.75,483.0,519344.0 -2024-08-09 11:20:00,10.75,10.76,10.75,10.75,401.0,431287.0 -2024-08-09 11:25:00,10.76,10.76,10.74,10.75,3346.0,3596701.0 -2024-08-09 11:30:00,10.74,10.75,10.7,10.71,1565.0,1678063.0 -2024-08-09 13:05:00,10.72,10.72,10.69,10.69,1942.0,2078552.0 -2024-08-09 13:10:00,10.69,10.69,10.67,10.68,1592.0,1700312.0 -2024-08-09 13:15:00,10.68,10.7,10.68,10.69,624.0,667166.0 -2024-08-09 13:20:00,10.7,10.7,10.69,10.69,352.0,376413.0 -2024-08-09 13:25:00,10.7,10.7,10.69,10.69,338.0,361623.0 -2024-08-09 13:30:00,10.69,10.7,10.69,10.7,555.0,593456.0 -2024-08-09 13:35:00,10.7,10.7,10.69,10.7,672.0,718815.0 -2024-08-09 13:40:00,10.7,10.71,10.69,10.69,300.0,320962.0 -2024-08-09 13:45:00,10.69,10.7,10.68,10.68,1167.0,1247251.0 -2024-08-09 13:50:00,10.68,10.69,10.67,10.68,1250.0,1334697.0 -2024-08-09 13:55:00,10.68,10.68,10.67,10.67,574.0,612649.0 -2024-08-09 14:00:00,10.67,10.68,10.66,10.66,1268.0,1353080.0 -2024-08-09 14:05:00,10.66,10.67,10.66,10.67,713.0,760474.0 -2024-08-09 14:10:00,10.67,10.68,10.66,10.67,1009.0,1076765.0 -2024-08-09 14:15:00,10.66,10.67,10.62,10.64,3534.0,3760861.0 -2024-08-09 14:20:00,10.64,10.64,10.63,10.63,1784.0,1896554.0 -2024-08-09 14:25:00,10.62,10.63,10.62,10.63,1602.0,1702115.0 -2024-08-09 14:30:00,10.63,10.64,10.62,10.64,1138.0,1209883.0 -2024-08-09 14:35:00,10.64,10.65,10.63,10.65,1975.0,2100840.0 -2024-08-09 14:40:00,10.63,10.66,10.63,10.65,685.0,729386.0 -2024-08-09 14:45:00,10.65,10.65,10.64,10.64,852.0,907163.0 -2024-08-09 14:50:00,10.64,10.66,10.64,10.64,1272.0,1354093.0 -2024-08-09 14:55:00,10.65,10.65,10.64,10.64,1290.0,1373219.0 -2024-08-09 15:00:00,10.64,10.66,10.63,10.63,2282.0,2427328.0 -2024-08-12 09:35:00,10.6,10.61,10.53,10.57,7803.0,8246589.0 -2024-08-12 09:40:00,10.57,10.57,10.53,10.55,2936.0,3097309.0 -2024-08-12 09:45:00,10.55,10.57,10.53,10.55,1857.0,1959038.0 -2024-08-12 09:50:00,10.55,10.57,10.51,10.52,3601.0,3793826.0 -2024-08-12 09:55:00,10.53,10.56,10.53,10.56,1337.0,1410021.0 -2024-08-12 10:00:00,10.56,10.56,10.54,10.56,735.0,775530.0 -2024-08-12 10:05:00,10.55,10.59,10.55,10.59,1128.0,1192955.0 -2024-08-12 10:10:00,10.59,10.59,10.56,10.57,844.0,892608.0 -2024-08-12 10:15:00,10.58,10.62,10.58,10.61,1247.0,1321882.0 -2024-08-12 10:20:00,10.61,10.64,10.6,10.64,959.0,1017981.0 -2024-08-12 10:25:00,10.64,10.68,10.62,10.65,1995.0,2124782.0 -2024-08-12 10:30:00,10.65,10.68,10.64,10.67,962.0,1025105.0 -2024-08-12 10:35:00,10.67,10.7,10.66,10.68,922.0,984254.0 -2024-08-12 10:40:00,10.69,10.69,10.66,10.69,1484.0,1584355.0 -2024-08-12 10:45:00,10.69,10.7,10.65,10.67,926.0,988787.0 -2024-08-12 10:50:00,10.66,10.7,10.66,10.69,824.0,880200.0 -2024-08-12 10:55:00,10.68,10.69,10.66,10.66,342.0,365074.0 -2024-08-12 11:00:00,10.67,10.67,10.63,10.63,349.0,371649.0 -2024-08-12 11:05:00,10.63,10.65,10.62,10.64,796.0,846497.0 -2024-08-12 11:10:00,10.63,10.64,10.62,10.63,113.0,120115.0 -2024-08-12 11:15:00,10.64,10.64,10.62,10.63,296.0,314597.0 -2024-08-12 11:20:00,10.63,10.64,10.63,10.63,159.0,169045.0 -2024-08-12 11:25:00,10.63,10.65,10.63,10.64,637.0,677792.0 -2024-08-12 11:30:00,10.63,10.65,10.63,10.64,348.0,370087.0 -2024-08-12 13:05:00,10.65,10.67,10.62,10.67,556.0,591514.0 -2024-08-12 13:10:00,10.67,10.67,10.63,10.65,179.0,190575.0 -2024-08-12 13:15:00,10.65,10.66,10.64,10.64,450.0,479238.0 -2024-08-12 13:20:00,10.65,10.66,10.64,10.64,123.0,131005.0 -2024-08-12 13:25:00,10.64,10.66,10.64,10.64,438.0,466459.0 -2024-08-12 13:30:00,10.64,10.65,10.64,10.65,88.0,93681.0 -2024-08-12 13:35:00,10.65,10.65,10.62,10.63,413.0,439190.0 -2024-08-12 13:40:00,10.63,10.64,10.62,10.62,244.0,259230.0 -2024-08-12 13:45:00,10.62,10.63,10.61,10.61,322.0,341944.0 -2024-08-12 13:50:00,10.61,10.63,10.61,10.62,858.0,911116.0 -2024-08-12 13:55:00,10.62,10.63,10.61,10.62,275.0,291938.0 -2024-08-12 14:00:00,10.61,10.62,10.6,10.6,643.0,681845.0 -2024-08-12 14:05:00,10.61,10.61,10.59,10.6,1149.0,1216301.0 -2024-08-12 14:10:00,10.6,10.63,10.6,10.61,668.0,709118.0 -2024-08-12 14:15:00,10.61,10.62,10.59,10.61,374.0,396700.0 -2024-08-12 14:20:00,10.62,10.62,10.59,10.59,447.0,474174.0 -2024-08-12 14:25:00,10.6,10.6,10.58,10.59,431.0,456503.0 -2024-08-12 14:30:00,10.59,10.6,10.59,10.59,372.0,394080.0 -2024-08-12 14:35:00,10.59,10.61,10.59,10.59,924.0,979330.0 -2024-08-12 14:40:00,10.59,10.6,10.58,10.6,203.0,215003.0 -2024-08-12 14:45:00,10.6,10.6,10.58,10.59,618.0,654440.0 -2024-08-12 14:50:00,10.59,10.61,10.58,10.61,1267.0,1342716.0 -2024-08-12 14:55:00,10.62,10.62,10.6,10.61,283.0,300167.0 -2024-08-12 15:00:00,10.61,10.62,10.6,10.62,1107.0,1174848.0 -2024-08-13 09:35:00,10.58,10.67,10.54,10.54,2531.0,2677092.0 -2024-08-13 09:40:00,10.54,10.55,10.51,10.51,2335.0,2458889.0 -2024-08-13 09:45:00,10.52,10.55,10.49,10.54,3952.0,4152949.0 -2024-08-13 09:50:00,10.55,10.56,10.48,10.48,1717.0,1804275.0 -2024-08-13 09:55:00,10.49,10.51,10.47,10.48,1913.0,2006734.0 -2024-08-13 10:00:00,10.47,10.48,10.46,10.47,1246.0,1304511.0 -2024-08-13 10:05:00,10.48,10.5,10.46,10.49,1172.0,1227381.0 -2024-08-13 10:10:00,10.49,10.53,10.48,10.53,1279.0,1343939.0 -2024-08-13 10:15:00,10.54,10.54,10.5,10.51,966.0,1016158.0 -2024-08-13 10:20:00,10.52,10.53,10.51,10.52,1105.0,1162204.0 -2024-08-13 10:25:00,10.52,10.53,10.51,10.53,485.0,510076.0 -2024-08-13 10:30:00,10.52,10.53,10.52,10.53,508.0,534790.0 -2024-08-13 10:35:00,10.53,10.53,10.5,10.51,485.0,509769.0 -2024-08-13 10:40:00,10.5,10.51,10.5,10.5,323.0,339384.0 -2024-08-13 10:45:00,10.5,10.51,10.5,10.5,811.0,851578.0 -2024-08-13 10:50:00,10.49,10.51,10.49,10.5,447.0,469139.0 -2024-08-13 10:55:00,10.51,10.52,10.5,10.52,807.0,848237.0 -2024-08-13 11:00:00,10.52,10.52,10.51,10.52,259.0,272276.0 -2024-08-13 11:05:00,10.51,10.52,10.47,10.47,1556.0,1631934.0 -2024-08-13 11:10:00,10.48,10.5,10.47,10.47,1225.0,1283798.0 -2024-08-13 11:15:00,10.47,10.48,10.45,10.45,1416.0,1480713.0 -2024-08-13 11:20:00,10.45,10.46,10.43,10.44,2271.0,2371811.0 -2024-08-13 11:25:00,10.44,10.44,10.42,10.43,1226.0,1278804.0 -2024-08-13 11:30:00,10.43,10.43,10.42,10.42,971.0,1012279.0 -2024-08-13 13:05:00,10.43,10.45,10.42,10.45,1348.0,1406353.0 -2024-08-13 13:10:00,10.44,10.44,10.43,10.44,419.0,437073.0 -2024-08-13 13:15:00,10.43,10.44,10.42,10.44,1605.0,1673299.0 -2024-08-13 13:20:00,10.44,10.46,10.44,10.45,789.0,824285.0 -2024-08-13 13:25:00,10.44,10.45,10.43,10.44,1949.0,2033836.0 -2024-08-13 13:30:00,10.44,10.44,10.43,10.44,410.0,427936.0 -2024-08-13 13:35:00,10.43,10.44,10.42,10.42,926.0,965313.0 -2024-08-13 13:40:00,10.41,10.42,10.41,10.41,332.0,345686.0 -2024-08-13 13:45:00,10.42,10.42,10.41,10.42,916.0,954470.0 -2024-08-13 13:50:00,10.42,10.42,10.41,10.42,696.0,724590.0 -2024-08-13 13:55:00,10.42,10.42,10.39,10.41,1718.0,1787640.0 -2024-08-13 14:00:00,10.4,10.41,10.4,10.41,376.0,391361.0 -2024-08-13 14:05:00,10.4,10.41,10.4,10.4,429.0,446169.0 -2024-08-13 14:10:00,10.4,10.42,10.4,10.4,628.0,653485.0 -2024-08-13 14:15:00,10.4,10.4,10.36,10.37,2171.0,2253145.0 -2024-08-13 14:20:00,10.37,10.38,10.37,10.38,696.0,722146.0 -2024-08-13 14:25:00,10.38,10.4,10.37,10.38,1204.0,1249986.0 -2024-08-13 14:30:00,10.38,10.4,10.37,10.39,731.0,758896.0 -2024-08-13 14:35:00,10.38,10.4,10.38,10.4,170.0,176657.0 -2024-08-13 14:40:00,10.4,10.4,10.38,10.4,1786.0,1855824.0 -2024-08-13 14:45:00,10.4,10.44,10.4,10.43,1141.0,1188229.0 -2024-08-13 14:50:00,10.44,10.44,10.42,10.44,583.0,608392.0 -2024-08-13 14:55:00,10.43,10.47,10.43,10.47,2292.0,2396543.0 -2024-08-13 15:00:00,10.47,10.47,10.45,10.45,1013.0,1059455.0 -2024-08-14 09:35:00,10.46,10.48,10.42,10.46,1977.0,2066756.0 -2024-08-14 09:40:00,10.46,10.46,10.42,10.45,1270.0,1325423.0 -2024-08-14 09:45:00,10.44,10.45,10.39,10.4,1754.0,1825616.0 -2024-08-14 09:50:00,10.4,10.44,10.39,10.42,953.0,992501.0 -2024-08-14 09:55:00,10.42,10.43,10.41,10.43,848.0,883431.0 -2024-08-14 10:00:00,10.41,10.42,10.4,10.4,487.0,506869.0 -2024-08-14 10:05:00,10.4,10.42,10.37,10.41,1481.0,1539263.0 -2024-08-14 10:10:00,10.42,10.44,10.41,10.44,641.0,668430.0 -2024-08-14 10:15:00,10.44,10.44,10.38,10.38,1669.0,1736378.0 -2024-08-14 10:20:00,10.38,10.41,10.38,10.4,223.0,231831.0 -2024-08-14 10:25:00,10.4,10.4,10.37,10.37,1643.0,1705727.0 -2024-08-14 10:30:00,10.37,10.41,10.37,10.4,764.0,793832.0 -2024-08-14 10:35:00,10.4,10.46,10.4,10.44,1452.0,1515740.0 -2024-08-14 10:40:00,10.43,10.46,10.42,10.46,835.0,872947.0 -2024-08-14 10:45:00,10.45,10.5,10.45,10.49,1527.0,1599208.0 -2024-08-14 10:50:00,10.49,10.52,10.49,10.51,2170.0,2278675.0 -2024-08-14 10:55:00,10.5,10.52,10.49,10.52,1471.0,1545817.0 -2024-08-14 11:00:00,10.52,10.53,10.49,10.5,919.0,966130.0 -2024-08-14 11:05:00,10.5,10.5,10.48,10.48,333.0,349358.0 -2024-08-14 11:10:00,10.48,10.49,10.48,10.49,135.0,141610.0 -2024-08-14 11:15:00,10.48,10.49,10.48,10.49,438.0,459341.0 -2024-08-14 11:20:00,10.49,10.5,10.49,10.5,437.0,458448.0 -2024-08-14 11:25:00,10.49,10.51,10.48,10.5,769.0,807069.0 -2024-08-14 11:30:00,10.5,10.5,10.49,10.5,222.0,233016.0 -2024-08-14 13:05:00,10.49,10.5,10.47,10.47,1534.0,1608817.0 -2024-08-14 13:10:00,10.47,10.49,10.46,10.48,761.0,797653.0 -2024-08-14 13:15:00,10.48,10.49,10.47,10.47,360.0,377131.0 -2024-08-14 13:20:00,10.47,10.5,10.47,10.49,694.0,728116.0 -2024-08-14 13:25:00,10.5,10.5,10.48,10.49,822.0,862283.0 -2024-08-14 13:30:00,10.48,10.48,10.46,10.46,859.0,899450.0 -2024-08-14 13:35:00,10.46,10.49,10.46,10.49,1425.0,1492360.0 -2024-08-14 13:40:00,10.49,10.5,10.48,10.49,882.0,925278.0 -2024-08-14 13:45:00,10.5,10.5,10.46,10.46,1656.0,1736698.0 -2024-08-14 13:50:00,10.46,10.46,10.44,10.45,1055.0,1102422.0 -2024-08-14 13:55:00,10.44,10.45,10.43,10.43,537.0,560662.0 -2024-08-14 14:00:00,10.44,10.45,10.43,10.44,923.0,963853.0 -2024-08-14 14:05:00,10.44,10.47,10.44,10.46,415.0,433888.0 -2024-08-14 14:10:00,10.45,10.45,10.44,10.44,249.0,260109.0 -2024-08-14 14:15:00,10.45,10.45,10.43,10.44,975.0,1018008.0 -2024-08-14 14:20:00,10.44,10.44,10.43,10.44,690.0,720189.0 -2024-08-14 14:25:00,10.44,10.46,10.44,10.44,1010.0,1054902.0 -2024-08-14 14:30:00,10.45,10.45,10.44,10.44,757.0,790964.0 -2024-08-14 14:35:00,10.44,10.46,10.44,10.45,872.0,911516.0 -2024-08-14 14:40:00,10.45,10.46,10.43,10.44,1012.0,1056283.0 -2024-08-14 14:45:00,10.43,10.44,10.41,10.42,1488.0,1550504.0 -2024-08-14 14:50:00,10.42,10.43,10.4,10.41,2479.0,2581636.0 -2024-08-14 14:55:00,10.41,10.43,10.4,10.41,1524.0,1585717.0 -2024-08-14 15:00:00,10.41,10.42,10.39,10.39,1283.0,1333819.0 -2024-08-15 09:35:00,10.4,10.44,10.34,10.38,4123.0,4285286.0 -2024-08-15 09:40:00,10.38,10.39,10.35,10.38,1410.0,1461662.0 -2024-08-15 09:45:00,10.37,10.4,10.35,10.35,3441.0,3566292.0 -2024-08-15 09:50:00,10.36,10.36,10.34,10.35,1188.0,1229420.0 -2024-08-15 09:55:00,10.35,10.36,10.32,10.34,1997.0,2064248.0 -2024-08-15 10:00:00,10.34,10.37,10.32,10.36,2912.0,3013733.0 -2024-08-15 10:05:00,10.37,10.38,10.36,10.38,1018.0,1055985.0 -2024-08-15 10:10:00,10.39,10.48,10.39,10.46,3612.0,3768187.0 -2024-08-15 10:15:00,10.47,10.53,10.47,10.53,5696.0,5978466.0 -2024-08-15 10:20:00,10.54,10.62,10.54,10.62,7032.0,7430496.0 -2024-08-15 10:25:00,10.61,10.66,10.61,10.65,7017.0,7462428.0 -2024-08-15 10:30:00,10.65,10.67,10.64,10.67,3637.0,3874718.0 -2024-08-15 10:35:00,10.66,10.7,10.66,10.68,5522.0,5898611.0 -2024-08-15 10:40:00,10.67,10.69,10.64,10.66,2376.0,2535747.0 -2024-08-15 10:45:00,10.65,10.66,10.63,10.65,2392.0,2546357.0 -2024-08-15 10:50:00,10.64,10.66,10.62,10.62,961.0,1021924.0 -2024-08-15 10:55:00,10.62,10.64,10.6,10.6,941.0,998605.0 -2024-08-15 11:00:00,10.61,10.63,10.61,10.61,1151.0,1221845.0 -2024-08-15 11:05:00,10.62,10.63,10.6,10.6,646.0,685941.0 -2024-08-15 11:10:00,10.6,10.61,10.6,10.61,609.0,645998.0 -2024-08-15 11:15:00,10.61,10.61,10.59,10.59,828.0,877734.0 -2024-08-15 11:20:00,10.59,10.62,10.59,10.62,1280.0,1358053.0 -2024-08-15 11:25:00,10.62,10.62,10.6,10.62,248.0,263216.0 -2024-08-15 11:30:00,10.62,10.63,10.61,10.62,224.0,237897.0 -2024-08-15 13:05:00,10.62,10.63,10.6,10.6,877.0,930531.0 -2024-08-15 13:10:00,10.59,10.6,10.56,10.59,3052.0,3226751.0 -2024-08-15 13:15:00,10.58,10.61,10.58,10.59,2585.0,2739663.0 -2024-08-15 13:20:00,10.59,10.59,10.56,10.57,636.0,672395.0 -2024-08-15 13:25:00,10.57,10.58,10.56,10.57,671.0,709316.0 -2024-08-15 13:30:00,10.57,10.57,10.56,10.57,513.0,541961.0 -2024-08-15 13:35:00,10.56,10.57,10.54,10.54,1227.0,1295073.0 -2024-08-15 13:40:00,10.55,10.56,10.54,10.55,778.0,820564.0 -2024-08-15 13:45:00,10.55,10.56,10.55,10.56,678.0,715745.0 -2024-08-15 13:50:00,10.56,10.57,10.54,10.54,786.0,829838.0 -2024-08-15 13:55:00,10.55,10.56,10.54,10.56,498.0,525559.0 -2024-08-15 14:00:00,10.56,10.56,10.55,10.56,332.0,350352.0 -2024-08-15 14:05:00,10.56,10.56,10.54,10.56,521.0,549605.0 -2024-08-15 14:10:00,10.55,10.56,10.54,10.55,463.0,488389.0 -2024-08-15 14:15:00,10.54,10.55,10.53,10.54,319.0,336180.0 -2024-08-15 14:20:00,10.54,10.55,10.54,10.55,396.0,417667.0 -2024-08-15 14:25:00,10.55,10.59,10.55,10.58,1589.0,1679873.0 -2024-08-15 14:30:00,10.59,10.6,10.57,10.59,502.0,531411.0 -2024-08-15 14:35:00,10.58,10.59,10.57,10.57,487.0,515221.0 -2024-08-15 14:40:00,10.57,10.57,10.56,10.56,524.0,553562.0 -2024-08-15 14:45:00,10.56,10.58,10.56,10.57,841.0,888483.0 -2024-08-15 14:50:00,10.57,10.6,10.57,10.6,1073.0,1135802.0 -2024-08-15 14:55:00,10.6,10.6,10.59,10.59,1579.0,1673409.0 -2024-08-15 15:00:00,10.6,10.62,10.59,10.59,2021.0,2141856.0 -2024-08-16 09:35:00,10.52,10.56,10.44,10.46,4743.0,4977813.0 -2024-08-16 09:40:00,10.47,10.48,10.45,10.46,2900.0,3033810.0 -2024-08-16 09:45:00,10.45,10.46,10.42,10.43,2472.0,2580525.0 -2024-08-16 09:50:00,10.45,10.46,10.43,10.44,808.0,843893.0 -2024-08-16 09:55:00,10.45,10.48,10.43,10.46,1611.0,1684760.0 -2024-08-16 10:00:00,10.47,10.49,10.46,10.49,2071.0,2169390.0 -2024-08-16 10:05:00,10.49,10.5,10.46,10.46,1388.0,1454609.0 -2024-08-16 10:10:00,10.46,10.46,10.44,10.46,926.0,967797.0 -2024-08-16 10:15:00,10.46,10.46,10.44,10.45,673.0,703217.0 -2024-08-16 10:20:00,10.46,10.47,10.44,10.45,835.0,873493.0 -2024-08-16 10:25:00,10.46,10.46,10.44,10.46,793.0,828950.0 -2024-08-16 10:30:00,10.45,10.46,10.44,10.44,491.0,513112.0 -2024-08-16 10:35:00,10.45,10.45,10.44,10.45,842.0,879270.0 -2024-08-16 10:40:00,10.45,10.46,10.44,10.45,203.0,212125.0 -2024-08-16 10:45:00,10.46,10.46,10.42,10.43,1672.0,1744868.0 -2024-08-16 10:50:00,10.43,10.43,10.42,10.42,352.0,366839.0 -2024-08-16 10:55:00,10.43,10.44,10.42,10.43,684.0,713373.0 -2024-08-16 11:00:00,10.42,10.43,10.4,10.4,2194.0,2284518.0 -2024-08-16 11:05:00,10.41,10.42,10.4,10.42,592.0,615925.0 -2024-08-16 11:10:00,10.42,10.44,10.42,10.44,260.0,271058.0 -2024-08-16 11:15:00,10.44,10.47,10.43,10.47,1382.0,1444627.0 -2024-08-16 11:20:00,10.46,10.48,10.46,10.47,421.0,440847.0 -2024-08-16 11:25:00,10.47,10.48,10.46,10.46,367.0,384357.0 -2024-08-16 11:30:00,10.46,10.47,10.45,10.47,504.0,526938.0 -2024-08-16 13:05:00,10.47,10.47,10.44,10.45,357.0,373276.0 -2024-08-16 13:10:00,10.45,10.48,10.45,10.46,1222.0,1279446.0 -2024-08-16 13:15:00,10.46,10.48,10.44,10.45,1499.0,1566120.0 -2024-08-16 13:20:00,10.45,10.46,10.43,10.43,630.0,658067.0 -2024-08-16 13:25:00,10.43,10.45,10.43,10.43,849.0,885725.0 -2024-08-16 13:30:00,10.43,10.44,10.42,10.42,816.0,850763.0 -2024-08-16 13:35:00,10.42,10.44,10.41,10.43,892.0,929560.0 -2024-08-16 13:40:00,10.41,10.43,10.4,10.4,1336.0,1390850.0 -2024-08-16 13:45:00,10.41,10.42,10.4,10.41,830.0,863495.0 -2024-08-16 13:50:00,10.42,10.42,10.4,10.42,370.0,385389.0 -2024-08-16 13:55:00,10.42,10.42,10.41,10.41,544.0,566724.0 -2024-08-16 14:00:00,10.41,10.43,10.41,10.43,560.0,583496.0 -2024-08-16 14:05:00,10.42,10.43,10.4,10.43,1555.0,1619412.0 -2024-08-16 14:10:00,10.43,10.44,10.41,10.42,587.0,611993.0 -2024-08-16 14:15:00,10.42,10.42,10.4,10.41,483.0,502834.0 -2024-08-16 14:20:00,10.41,10.42,10.4,10.42,526.0,547503.0 -2024-08-16 14:25:00,10.42,10.42,10.4,10.42,847.0,881940.0 -2024-08-16 14:30:00,10.41,10.43,10.41,10.42,765.0,796892.0 -2024-08-16 14:35:00,10.42,10.43,10.4,10.41,1087.0,1131773.0 -2024-08-16 14:40:00,10.4,10.42,10.4,10.41,707.0,736034.0 -2024-08-16 14:45:00,10.41,10.43,10.41,10.42,725.0,755665.0 -2024-08-16 14:50:00,10.43,10.43,10.41,10.43,1262.0,1315074.0 -2024-08-16 14:55:00,10.43,10.44,10.42,10.44,1886.0,1966774.0 -2024-08-16 15:00:00,10.42,10.45,10.42,10.42,3053.0,3184562.0 -2024-08-19 09:35:00,10.48,10.48,10.4,10.45,3487.0,3640377.0 -2024-08-19 09:40:00,10.45,10.57,10.44,10.55,5256.0,5534019.0 -2024-08-19 09:45:00,10.54,10.58,10.53,10.54,4624.0,4883221.0 -2024-08-19 09:50:00,10.54,10.55,10.5,10.52,1354.0,1425755.0 -2024-08-19 09:55:00,10.51,10.55,10.48,10.54,2280.0,2395324.0 -2024-08-19 10:00:00,10.55,10.55,10.53,10.54,992.0,1045692.0 -2024-08-19 10:05:00,10.54,10.55,10.49,10.5,1405.0,1478376.0 -2024-08-19 10:10:00,10.5,10.5,10.48,10.49,815.0,854767.0 -2024-08-19 10:15:00,10.49,10.49,10.47,10.48,640.0,670680.0 -2024-08-19 10:20:00,10.49,10.49,10.47,10.48,947.0,992661.0 -2024-08-19 10:25:00,10.48,10.49,10.47,10.47,791.0,829397.0 -2024-08-19 10:30:00,10.48,10.49,10.47,10.49,668.0,700056.0 -2024-08-19 10:35:00,10.49,10.49,10.47,10.47,899.0,941439.0 -2024-08-19 10:40:00,10.47,10.49,10.46,10.48,1204.0,1261535.0 -2024-08-19 10:45:00,10.48,10.48,10.46,10.46,559.0,585411.0 -2024-08-19 10:50:00,10.46,10.48,10.46,10.48,358.0,374762.0 -2024-08-19 10:55:00,10.47,10.47,10.46,10.47,249.0,260653.0 -2024-08-19 11:00:00,10.47,10.52,10.47,10.5,2181.0,2290255.0 -2024-08-19 11:05:00,10.5,10.51,10.47,10.49,414.0,434603.0 -2024-08-19 11:10:00,10.48,10.49,10.48,10.48,138.0,144652.0 -2024-08-19 11:15:00,10.49,10.49,10.48,10.48,183.0,191876.0 -2024-08-19 11:20:00,10.49,10.52,10.47,10.52,1218.0,1278715.0 -2024-08-19 11:25:00,10.51,10.52,10.5,10.51,777.0,816547.0 -2024-08-19 11:30:00,10.51,10.53,10.51,10.52,527.0,554316.0 -2024-08-19 13:05:00,10.52,10.52,10.49,10.49,925.0,972253.0 -2024-08-19 13:10:00,10.49,10.49,10.47,10.48,311.0,325934.0 -2024-08-19 13:15:00,10.47,10.48,10.46,10.47,362.0,379024.0 -2024-08-19 13:20:00,10.47,10.47,10.46,10.47,244.0,255404.0 -2024-08-19 13:25:00,10.46,10.47,10.45,10.46,529.0,553300.0 -2024-08-19 13:30:00,10.46,10.47,10.46,10.46,132.0,138076.0 -2024-08-19 13:35:00,10.46,10.47,10.44,10.45,1102.0,1152152.0 -2024-08-19 13:40:00,10.45,10.46,10.44,10.45,394.0,411641.0 -2024-08-19 13:45:00,10.46,10.46,10.44,10.44,755.0,788603.0 -2024-08-19 13:50:00,10.43,10.44,10.43,10.44,287.0,299566.0 -2024-08-19 13:55:00,10.44,10.44,10.43,10.43,124.0,129379.0 -2024-08-19 14:00:00,10.43,10.45,10.43,10.44,387.0,403986.0 -2024-08-19 14:05:00,10.45,10.45,10.43,10.44,656.0,684884.0 -2024-08-19 14:10:00,10.45,10.45,10.43,10.44,228.0,238026.0 -2024-08-19 14:15:00,10.44,10.44,10.42,10.43,680.0,709351.0 -2024-08-19 14:20:00,10.42,10.43,10.42,10.42,216.0,225106.0 -2024-08-19 14:25:00,10.42,10.44,10.42,10.44,477.0,497495.0 -2024-08-19 14:30:00,10.43,10.46,10.43,10.45,1025.0,1070594.0 -2024-08-19 14:35:00,10.46,10.46,10.44,10.46,958.0,1001186.0 -2024-08-19 14:40:00,10.46,10.46,10.45,10.45,594.0,621168.0 -2024-08-19 14:45:00,10.45,10.46,10.45,10.45,281.0,293753.0 -2024-08-19 14:50:00,10.45,10.46,10.44,10.45,1280.0,1337340.0 -2024-08-19 14:55:00,10.45,10.48,10.45,10.48,1042.0,1090735.0 -2024-08-19 15:00:00,10.47,10.48,10.45,10.45,962.0,1006885.0 -2024-08-20 09:35:00,10.47,10.48,10.35,10.37,4896.0,5085952.0 -2024-08-20 09:40:00,10.39,10.45,10.35,10.44,2218.0,2304656.0 -2024-08-20 09:45:00,10.44,10.51,10.44,10.5,2345.0,2458151.0 -2024-08-20 09:50:00,10.49,10.49,10.45,10.46,851.0,890914.0 -2024-08-20 09:55:00,10.46,10.46,10.42,10.42,778.0,812459.0 -2024-08-20 10:00:00,10.42,10.42,10.38,10.39,1214.0,1262367.0 -2024-08-20 10:05:00,10.39,10.39,10.36,10.36,1740.0,1803967.0 -2024-08-20 10:10:00,10.36,10.37,10.33,10.35,2483.0,2570029.0 -2024-08-20 10:15:00,10.35,10.36,10.34,10.36,501.0,518403.0 -2024-08-20 10:20:00,10.36,10.36,10.34,10.35,1440.0,1490103.0 -2024-08-20 10:25:00,10.34,10.36,10.32,10.32,1575.0,1628207.0 -2024-08-20 10:30:00,10.33,10.33,10.31,10.31,985.0,1016216.0 -2024-08-20 10:35:00,10.31,10.31,10.29,10.3,1739.0,1791741.0 -2024-08-20 10:40:00,10.3,10.31,10.29,10.31,793.0,817286.0 -2024-08-20 10:45:00,10.3,10.32,10.29,10.3,2159.0,2224792.0 -2024-08-20 10:50:00,10.3,10.3,10.29,10.29,736.0,757836.0 -2024-08-20 10:55:00,10.29,10.3,10.29,10.29,727.0,748439.0 -2024-08-20 11:00:00,10.29,10.3,10.28,10.29,962.0,990032.0 -2024-08-20 11:05:00,10.29,10.33,10.28,10.32,2639.0,2719803.0 -2024-08-20 11:10:00,10.31,10.35,10.31,10.33,1603.0,1655620.0 -2024-08-20 11:15:00,10.34,10.36,10.32,10.35,1634.0,1690239.0 -2024-08-20 11:20:00,10.35,10.35,10.32,10.33,579.0,598345.0 -2024-08-20 11:25:00,10.32,10.33,10.3,10.32,736.0,759504.0 -2024-08-20 11:30:00,10.32,10.33,10.3,10.31,528.0,544606.0 -2024-08-20 13:05:00,10.31,10.37,10.3,10.35,2028.0,2098114.0 -2024-08-20 13:10:00,10.35,10.36,10.33,10.35,599.0,619513.0 -2024-08-20 13:15:00,10.35,10.38,10.34,10.35,1047.0,1084930.0 -2024-08-20 13:20:00,10.34,10.36,10.34,10.34,289.0,299019.0 -2024-08-20 13:25:00,10.34,10.37,10.34,10.37,1791.0,1854786.0 -2024-08-20 13:30:00,10.37,10.37,10.35,10.35,478.0,495143.0 -2024-08-20 13:35:00,10.35,10.35,10.33,10.34,281.0,290647.0 -2024-08-20 13:40:00,10.35,10.36,10.34,10.34,513.0,530869.0 -2024-08-20 13:45:00,10.33,10.34,10.32,10.32,427.0,441138.0 -2024-08-20 13:50:00,10.33,10.34,10.31,10.34,581.0,599869.0 -2024-08-20 13:55:00,10.34,10.34,10.32,10.32,383.0,395651.0 -2024-08-20 14:00:00,10.33,10.36,10.32,10.33,929.0,960741.0 -2024-08-20 14:05:00,10.33,10.33,10.31,10.32,580.0,598531.0 -2024-08-20 14:10:00,10.32,10.33,10.31,10.31,287.0,296157.0 -2024-08-20 14:15:00,10.32,10.32,10.31,10.31,489.0,504329.0 -2024-08-20 14:20:00,10.31,10.33,10.3,10.32,867.0,894207.0 -2024-08-20 14:25:00,10.33,10.33,10.31,10.31,658.0,679007.0 -2024-08-20 14:30:00,10.32,10.34,10.31,10.34,870.0,898517.0 -2024-08-20 14:35:00,10.35,10.36,10.32,10.33,529.0,546893.0 -2024-08-20 14:40:00,10.33,10.36,10.33,10.35,598.0,618682.0 -2024-08-20 14:45:00,10.34,10.35,10.33,10.34,643.0,664936.0 -2024-08-20 14:50:00,10.34,10.35,10.33,10.34,966.0,998519.0 -2024-08-20 14:55:00,10.34,10.35,10.33,10.35,1380.0,1426480.0 -2024-08-20 15:00:00,10.34,10.36,10.34,10.34,1083.0,1120146.0 -2024-08-21 09:35:00,10.3,10.37,10.23,10.3,4412.0,4540566.0 -2024-08-21 09:40:00,10.3,10.35,10.3,10.34,1071.0,1105920.0 -2024-08-21 09:45:00,10.34,10.41,10.33,10.4,1828.0,1896882.0 -2024-08-21 09:50:00,10.4,10.41,10.37,10.39,1048.0,1089150.0 -2024-08-21 09:55:00,10.38,10.38,10.34,10.37,897.0,929287.0 -2024-08-21 10:00:00,10.36,10.37,10.33,10.34,608.0,629205.0 -2024-08-21 10:05:00,10.33,10.36,10.33,10.35,897.0,927618.0 -2024-08-21 10:10:00,10.35,10.36,10.34,10.35,311.0,321839.0 -2024-08-21 10:15:00,10.35,10.36,10.34,10.35,315.0,326036.0 -2024-08-21 10:20:00,10.34,10.37,10.34,10.37,562.0,582032.0 -2024-08-21 10:25:00,10.37,10.38,10.35,10.36,637.0,660163.0 -2024-08-21 10:30:00,10.34,10.35,10.32,10.32,616.0,636956.0 -2024-08-21 10:35:00,10.33,10.34,10.3,10.31,1360.0,1403491.0 -2024-08-21 10:40:00,10.32,10.34,10.29,10.29,743.0,766543.0 -2024-08-21 10:45:00,10.29,10.31,10.29,10.3,380.0,391304.0 -2024-08-21 10:50:00,10.3,10.31,10.29,10.29,534.0,549974.0 -2024-08-21 10:55:00,10.29,10.31,10.27,10.29,1478.0,1520742.0 -2024-08-21 11:00:00,10.29,10.34,10.28,10.33,1447.0,1492192.0 -2024-08-21 11:05:00,10.31,10.37,10.3,10.33,1059.0,1095330.0 -2024-08-21 11:10:00,10.32,10.33,10.32,10.32,240.0,247699.0 -2024-08-21 11:15:00,10.33,10.33,10.31,10.31,313.0,322842.0 -2024-08-21 11:20:00,10.33,10.33,10.29,10.31,303.0,312177.0 -2024-08-21 11:25:00,10.3,10.3,10.29,10.29,265.0,272740.0 -2024-08-21 11:30:00,10.3,10.3,10.29,10.3,168.0,172887.0 -2024-08-21 13:05:00,10.29,10.29,10.27,10.29,888.0,913207.0 -2024-08-21 13:10:00,10.28,10.29,10.25,10.27,1394.0,1431181.0 -2024-08-21 13:15:00,10.26,10.27,10.24,10.24,1229.0,1260133.0 -2024-08-21 13:20:00,10.24,10.26,10.24,10.24,1142.0,1170053.0 -2024-08-21 13:25:00,10.24,10.25,10.22,10.24,1476.0,1510011.0 -2024-08-21 13:30:00,10.23,10.24,10.23,10.24,2004.0,2051754.0 -2024-08-21 13:35:00,10.23,10.25,10.23,10.23,2243.0,2296830.0 -2024-08-21 13:40:00,10.23,10.24,10.22,10.22,1147.0,1173538.0 -2024-08-21 13:45:00,10.22,10.24,10.22,10.23,404.0,413329.0 -2024-08-21 13:50:00,10.23,10.24,10.22,10.23,692.0,707924.0 -2024-08-21 13:55:00,10.23,10.25,10.23,10.25,961.0,984258.0 -2024-08-21 14:00:00,10.24,10.25,10.24,10.24,279.0,286089.0 -2024-08-21 14:05:00,10.24,10.25,10.23,10.24,1036.0,1060365.0 -2024-08-21 14:10:00,10.25,10.25,10.24,10.24,459.0,470190.0 -2024-08-21 14:15:00,10.24,10.25,10.24,10.24,388.0,397448.0 -2024-08-21 14:20:00,10.24,10.25,10.23,10.24,931.0,953123.0 -2024-08-21 14:25:00,10.24,10.24,10.22,10.22,1216.0,1243922.0 -2024-08-21 14:30:00,10.22,10.23,10.22,10.22,970.0,991532.0 -2024-08-21 14:35:00,10.23,10.23,10.21,10.21,1529.0,1562363.0 -2024-08-21 14:40:00,10.21,10.22,10.2,10.2,2054.0,2096328.0 -2024-08-21 14:45:00,10.21,10.22,10.2,10.21,804.0,820753.0 -2024-08-21 14:50:00,10.21,10.22,10.2,10.21,1680.0,1714892.0 -2024-08-21 14:55:00,10.2,10.22,10.2,10.21,4058.0,4139661.0 -2024-08-21 15:00:00,10.2,10.21,10.2,10.21,1115.0,1137838.0 -2024-08-22 09:35:00,10.21,10.24,10.14,10.15,5045.0,5139720.0 -2024-08-22 09:40:00,10.15,10.16,10.1,10.12,3488.0,3531394.0 -2024-08-22 09:45:00,10.11,10.13,10.07,10.12,6049.0,6110364.0 -2024-08-22 09:50:00,10.12,10.12,10.08,10.09,4325.0,4365599.0 -2024-08-22 09:55:00,10.08,10.09,10.06,10.07,3752.0,3779795.0 -2024-08-22 10:00:00,10.06,10.07,10.03,10.03,3966.0,3984805.0 -2024-08-22 10:05:00,10.04,10.04,10.02,10.03,2473.0,2480066.0 -2024-08-22 10:10:00,10.03,10.04,10.03,10.04,767.0,769780.0 -2024-08-22 10:15:00,10.04,10.04,10.0,10.0,3760.0,3767976.0 -2024-08-22 10:20:00,10.0,10.01,9.98,10.0,4364.0,4361331.0 -2024-08-22 10:25:00,10.0,10.01,9.98,9.99,2134.0,2132824.0 -2024-08-22 10:30:00,9.99,9.99,9.97,9.99,2012.0,2008437.0 -2024-08-22 10:35:00,9.99,10.0,9.97,10.0,2220.0,2216576.0 -2024-08-22 10:40:00,9.99,9.99,9.97,9.97,1855.0,1851418.0 -2024-08-22 10:45:00,9.97,10.01,9.96,9.97,4110.0,4100874.0 -2024-08-22 10:50:00,9.98,9.98,9.91,9.93,3399.0,3379448.0 -2024-08-22 10:55:00,9.93,9.95,9.93,9.93,1934.0,1921170.0 -2024-08-22 11:00:00,9.93,9.95,9.93,9.93,1630.0,1619762.0 -2024-08-22 11:05:00,9.93,9.95,9.9,9.91,3521.0,3490676.0 -2024-08-22 11:10:00,9.9,9.91,9.88,9.9,3464.0,3427883.0 -2024-08-22 11:15:00,9.9,9.92,9.9,9.91,749.0,742143.0 -2024-08-22 11:20:00,9.91,9.92,9.9,9.92,784.0,777038.0 -2024-08-22 11:25:00,9.92,9.93,9.91,9.91,883.0,875824.0 -2024-08-22 11:30:00,9.92,9.92,9.9,9.92,986.0,977208.0 -2024-08-22 13:05:00,9.93,9.93,9.91,9.92,1353.0,1342535.0 -2024-08-22 13:10:00,9.92,9.92,9.9,9.91,754.0,747372.0 -2024-08-22 13:15:00,9.9,9.92,9.9,9.9,943.0,934438.0 -2024-08-22 13:20:00,9.9,9.91,9.89,9.9,1986.0,1966223.0 -2024-08-22 13:25:00,9.9,9.91,9.89,9.91,1590.0,1573958.0 -2024-08-22 13:30:00,9.91,9.92,9.9,9.92,1203.0,1192535.0 -2024-08-22 13:35:00,9.91,9.92,9.9,9.92,813.0,805967.0 -2024-08-22 13:40:00,9.91,9.92,9.89,9.89,1908.0,1889524.0 -2024-08-22 13:45:00,9.89,9.9,9.88,9.88,2846.0,2814637.0 -2024-08-22 13:50:00,9.89,9.89,9.87,9.88,2326.0,2297878.0 -2024-08-22 13:55:00,9.88,9.88,9.85,9.86,3234.0,3188702.0 -2024-08-22 14:00:00,9.85,9.86,9.83,9.83,2000.0,1969115.0 -2024-08-22 14:05:00,9.83,9.84,9.81,9.83,6481.0,6367009.0 -2024-08-22 14:10:00,9.84,9.84,9.8,9.81,5023.0,4930721.0 -2024-08-22 14:15:00,9.81,9.81,9.78,9.78,5599.0,5483942.0 -2024-08-22 14:20:00,9.78,9.81,9.78,9.81,2331.0,2285162.0 -2024-08-22 14:25:00,9.8,9.83,9.79,9.81,1805.0,1769936.0 -2024-08-22 14:30:00,9.81,9.83,9.8,9.81,2327.0,2284382.0 -2024-08-22 14:35:00,9.82,9.82,9.8,9.8,1799.0,1764103.0 -2024-08-22 14:40:00,9.8,9.81,9.79,9.8,1539.0,1507667.0 -2024-08-22 14:45:00,9.8,9.81,9.79,9.81,1389.0,1361187.0 -2024-08-22 14:50:00,9.81,9.82,9.79,9.81,2072.0,2031823.0 -2024-08-22 14:55:00,9.81,9.82,9.8,9.8,2027.0,1987621.0 -2024-08-22 15:00:00,9.8,9.82,9.8,9.82,2665.0,2615001.0 -2024-08-23 09:35:00,9.81,9.85,9.75,9.81,6235.0,6105743.0 -2024-08-23 09:40:00,9.81,9.83,9.78,9.8,2243.0,2200471.0 -2024-08-23 09:45:00,9.79,9.86,9.79,9.86,2667.0,2621868.0 -2024-08-23 09:50:00,9.86,9.89,9.83,9.86,2251.0,2218540.0 -2024-08-23 09:55:00,9.86,9.87,9.83,9.83,1575.0,1550820.0 -2024-08-23 10:00:00,9.83,9.83,9.8,9.81,596.0,584962.0 -2024-08-23 10:05:00,9.8,9.81,9.78,9.79,946.0,927116.0 -2024-08-23 10:10:00,9.79,9.83,9.79,9.82,1309.0,1285150.0 -2024-08-23 10:15:00,9.82,9.84,9.8,9.83,1577.0,1551249.0 -2024-08-23 10:20:00,9.84,9.85,9.83,9.83,734.0,722291.0 -2024-08-23 10:25:00,9.83,9.84,9.81,9.81,794.0,779853.0 -2024-08-23 10:30:00,9.81,9.81,9.8,9.8,419.0,410959.0 -2024-08-23 10:35:00,9.8,9.82,9.79,9.8,1118.0,1095862.0 -2024-08-23 10:40:00,9.81,9.84,9.81,9.82,476.0,467581.0 -2024-08-23 10:45:00,9.82,9.83,9.81,9.81,382.0,375004.0 -2024-08-23 10:50:00,9.81,9.82,9.81,9.82,274.0,269004.0 -2024-08-23 10:55:00,9.82,9.82,9.8,9.81,328.0,321782.0 -2024-08-23 11:00:00,9.82,9.82,9.8,9.8,920.0,902202.0 -2024-08-23 11:05:00,9.8,9.83,9.79,9.81,317.0,310991.0 -2024-08-23 11:10:00,9.82,9.85,9.81,9.83,543.0,534054.0 -2024-08-23 11:15:00,9.83,9.86,9.83,9.85,424.0,417600.0 -2024-08-23 11:20:00,9.84,9.88,9.82,9.88,1030.0,1015443.0 -2024-08-23 11:25:00,9.88,9.9,9.87,9.88,1631.0,1612142.0 -2024-08-23 11:30:00,9.88,9.88,9.85,9.86,708.0,698670.0 -2024-08-23 13:05:00,9.88,9.88,9.83,9.84,1018.0,1003023.0 -2024-08-23 13:10:00,9.83,9.83,9.81,9.81,806.0,791851.0 -2024-08-23 13:15:00,9.81,9.84,9.81,9.84,645.0,633856.0 -2024-08-23 13:20:00,9.84,9.84,9.81,9.84,443.0,435324.0 -2024-08-23 13:25:00,9.82,9.85,9.82,9.83,560.0,550859.0 -2024-08-23 13:30:00,9.83,9.85,9.83,9.84,454.0,446808.0 -2024-08-23 13:35:00,9.84,9.86,9.83,9.85,1063.0,1046462.0 -2024-08-23 13:40:00,9.84,9.86,9.84,9.85,688.0,677497.0 -2024-08-23 13:45:00,9.85,9.87,9.85,9.85,926.0,912863.0 -2024-08-23 13:50:00,9.85,9.86,9.83,9.85,440.0,433251.0 -2024-08-23 13:55:00,9.83,9.86,9.82,9.82,911.0,895498.0 -2024-08-23 14:00:00,9.84,9.84,9.8,9.8,2245.0,2202275.0 -2024-08-23 14:05:00,9.8,9.81,9.77,9.77,1748.0,1711494.0 -2024-08-23 14:10:00,9.79,9.79,9.76,9.76,1798.0,1756498.0 -2024-08-23 14:15:00,9.76,9.79,9.76,9.79,1236.0,1207886.0 -2024-08-23 14:20:00,9.77,9.81,9.77,9.8,588.0,575275.0 -2024-08-23 14:25:00,9.79,9.8,9.78,9.78,399.0,390550.0 -2024-08-23 14:30:00,9.8,9.8,9.78,9.8,721.0,705503.0 -2024-08-23 14:35:00,9.8,9.82,9.79,9.81,654.0,641272.0 -2024-08-23 14:40:00,9.81,9.83,9.8,9.81,497.0,487503.0 -2024-08-23 14:45:00,9.81,9.82,9.8,9.82,523.0,513254.0 -2024-08-23 14:50:00,9.8,9.83,9.8,9.83,799.0,784216.0 -2024-08-23 14:55:00,9.83,9.84,9.81,9.82,2150.0,2112695.0 -2024-08-23 15:00:00,9.84,9.84,9.82,9.82,922.0,905542.0 -2024-08-26 09:35:00,9.83,9.84,9.72,9.74,3488.0,3407579.0 -2024-08-26 09:40:00,9.73,9.75,9.71,9.74,3077.0,2993159.0 -2024-08-26 09:45:00,9.73,9.82,9.73,9.82,1445.0,1413972.0 -2024-08-26 09:50:00,9.81,9.85,9.78,9.85,1854.0,1821075.0 -2024-08-26 09:55:00,9.84,9.86,9.81,9.82,1371.0,1348275.0 -2024-08-26 10:00:00,9.82,9.85,9.8,9.83,1660.0,1631593.0 -2024-08-26 10:05:00,9.83,9.86,9.83,9.85,1449.0,1426677.0 -2024-08-26 10:10:00,9.86,9.89,9.85,9.88,2491.0,2456975.0 -2024-08-26 10:15:00,9.88,9.88,9.83,9.85,880.0,867455.0 -2024-08-26 10:20:00,9.85,9.86,9.83,9.85,878.0,863797.0 -2024-08-26 10:25:00,9.85,9.87,9.84,9.85,861.0,848744.0 -2024-08-26 10:30:00,9.86,9.87,9.85,9.86,1062.0,1047250.0 -2024-08-26 10:35:00,9.85,9.87,9.84,9.85,1128.0,1111544.0 -2024-08-26 10:40:00,9.84,9.85,9.81,9.82,1022.0,1004039.0 -2024-08-26 10:45:00,9.83,9.83,9.81,9.81,462.0,453564.0 -2024-08-26 10:50:00,9.81,9.81,9.79,9.79,660.0,646866.0 -2024-08-26 10:55:00,9.79,9.82,9.79,9.81,656.0,643344.0 -2024-08-26 11:00:00,9.81,9.81,9.78,9.79,589.0,576782.0 -2024-08-26 11:05:00,9.79,9.79,9.76,9.78,1052.0,1028891.0 -2024-08-26 11:10:00,9.79,9.79,9.78,9.78,439.0,429376.0 -2024-08-26 11:15:00,9.78,9.79,9.77,9.78,273.0,266992.0 -2024-08-26 11:20:00,9.79,9.8,9.77,9.78,697.0,682053.0 -2024-08-26 11:25:00,9.78,9.79,9.78,9.79,844.0,826132.0 -2024-08-26 11:30:00,9.78,9.8,9.77,9.78,929.0,908711.0 -2024-08-26 13:05:00,9.79,9.79,9.77,9.77,921.0,900205.0 -2024-08-26 13:10:00,9.78,9.78,9.77,9.78,186.0,181819.0 -2024-08-26 13:15:00,9.78,9.79,9.77,9.79,482.0,471638.0 -2024-08-26 13:20:00,9.79,9.81,9.79,9.79,439.0,430276.0 -2024-08-26 13:25:00,9.79,9.81,9.79,9.79,501.0,490671.0 -2024-08-26 13:30:00,9.8,9.8,9.79,9.8,95.0,93098.0 -2024-08-26 13:35:00,9.79,9.8,9.79,9.79,202.0,197776.0 -2024-08-26 13:40:00,9.79,9.79,9.77,9.78,447.0,437167.0 -2024-08-26 13:45:00,9.77,9.79,9.77,9.78,225.0,220068.0 -2024-08-26 13:50:00,9.79,9.79,9.77,9.78,620.0,606274.0 -2024-08-26 13:55:00,9.77,9.78,9.77,9.78,265.0,259106.0 -2024-08-26 14:00:00,9.78,9.79,9.78,9.78,390.0,381440.0 -2024-08-26 14:05:00,9.77,9.78,9.77,9.78,275.0,268888.0 -2024-08-26 14:10:00,9.78,9.79,9.77,9.78,888.0,868609.0 -2024-08-26 14:15:00,9.78,9.79,9.77,9.78,617.0,603625.0 -2024-08-26 14:20:00,9.77,9.78,9.76,9.76,1067.0,1042333.0 -2024-08-26 14:25:00,9.76,9.79,9.76,9.77,405.0,395876.0 -2024-08-26 14:30:00,9.79,9.79,9.77,9.78,699.0,683635.0 -2024-08-26 14:35:00,9.79,9.81,9.78,9.81,1016.0,994971.0 -2024-08-26 14:40:00,9.81,9.82,9.8,9.8,1507.0,1478486.0 -2024-08-26 14:45:00,9.8,9.8,9.79,9.8,866.0,848531.0 -2024-08-26 14:50:00,9.8,9.81,9.79,9.8,443.0,434167.0 -2024-08-26 14:55:00,9.81,9.82,9.8,9.81,867.0,850160.0 -2024-08-26 15:00:00,9.81,9.82,9.8,9.82,1020.0,1001599.0 -2024-08-27 09:35:00,9.75,9.79,9.74,9.78,3295.0,3216408.0 -2024-08-27 09:40:00,9.78,9.81,9.75,9.79,1741.0,1701995.0 -2024-08-27 09:45:00,9.79,9.81,9.76,9.76,1248.0,1220948.0 -2024-08-27 09:50:00,9.76,9.77,9.75,9.75,1114.0,1086882.0 -2024-08-27 09:55:00,9.75,9.76,9.72,9.73,2379.0,2316659.0 -2024-08-27 10:00:00,9.73,9.73,9.66,9.67,5890.0,5713088.0 -2024-08-27 10:05:00,9.67,9.67,9.64,9.65,2879.0,2778367.0 -2024-08-27 10:10:00,9.65,9.69,9.64,9.68,2059.0,1990830.0 -2024-08-27 10:15:00,9.67,9.69,9.66,9.66,696.0,673371.0 -2024-08-27 10:20:00,9.66,9.68,9.66,9.67,387.0,374292.0 -2024-08-27 10:25:00,9.68,9.68,9.67,9.68,500.0,483729.0 -2024-08-27 10:30:00,9.67,9.68,9.66,9.66,1016.0,982591.0 -2024-08-27 10:35:00,9.67,9.71,9.66,9.69,2360.0,2285796.0 -2024-08-27 10:40:00,9.69,9.71,9.69,9.71,610.0,591307.0 -2024-08-27 10:45:00,9.69,9.71,9.66,9.66,776.0,751204.0 -2024-08-27 10:50:00,9.66,9.68,9.66,9.67,1128.0,1090652.0 -2024-08-27 10:55:00,9.67,9.69,9.67,9.68,794.0,768548.0 -2024-08-27 11:00:00,9.68,9.68,9.66,9.67,1465.0,1416400.0 -2024-08-27 11:05:00,9.67,9.67,9.66,9.66,1020.0,986056.0 -2024-08-27 11:10:00,9.67,9.67,9.66,9.66,1084.0,1047774.0 -2024-08-27 11:15:00,9.66,9.67,9.66,9.66,202.0,195195.0 -2024-08-27 11:20:00,9.66,9.68,9.66,9.68,244.0,235829.0 -2024-08-27 11:25:00,9.68,9.7,9.67,9.68,481.0,465929.0 -2024-08-27 11:30:00,9.69,9.7,9.67,9.67,1430.0,1384393.0 -2024-08-27 13:05:00,9.67,9.69,9.65,9.65,2864.0,2767477.0 -2024-08-27 13:10:00,9.65,9.66,9.65,9.65,745.0,719014.0 -2024-08-27 13:15:00,9.66,9.66,9.65,9.65,379.0,365956.0 -2024-08-27 13:20:00,9.66,9.67,9.65,9.67,357.0,344911.0 -2024-08-27 13:25:00,9.66,9.68,9.66,9.68,203.0,196259.0 -2024-08-27 13:30:00,9.68,9.68,9.66,9.66,717.0,693121.0 -2024-08-27 13:35:00,9.66,9.67,9.66,9.67,155.0,149798.0 -2024-08-27 13:40:00,9.67,9.68,9.66,9.67,350.0,338444.0 -2024-08-27 13:45:00,9.68,9.68,9.66,9.67,284.0,274569.0 -2024-08-27 13:50:00,9.68,9.68,9.66,9.66,789.0,762883.0 -2024-08-27 13:55:00,9.66,9.67,9.66,9.66,210.0,202927.0 -2024-08-27 14:00:00,9.66,9.67,9.65,9.67,1308.0,1263960.0 -2024-08-27 14:05:00,9.66,9.67,9.66,9.67,399.0,385695.0 -2024-08-27 14:10:00,9.66,9.67,9.66,9.67,233.0,225118.0 -2024-08-27 14:15:00,9.67,9.67,9.65,9.66,1214.0,1172290.0 -2024-08-27 14:20:00,9.66,9.67,9.65,9.67,752.0,726377.0 -2024-08-27 14:25:00,9.67,9.67,9.65,9.66,1297.0,1253040.0 -2024-08-27 14:30:00,9.66,9.67,9.66,9.66,464.0,448360.0 -2024-08-27 14:35:00,9.66,9.67,9.64,9.65,2474.0,2388191.0 -2024-08-27 14:40:00,9.66,9.66,9.64,9.65,1516.0,1463224.0 -2024-08-27 14:45:00,9.65,9.67,9.65,9.65,635.0,613312.0 -2024-08-27 14:50:00,9.66,9.67,9.65,9.66,1042.0,1007307.0 -2024-08-27 14:55:00,9.66,9.67,9.66,9.66,674.0,651411.0 -2024-08-27 15:00:00,9.67,9.68,9.66,9.67,1140.0,1101826.0 -2024-08-28 09:35:00,9.66,9.71,9.64,9.66,4140.0,4003153.0 -2024-08-28 09:40:00,9.65,9.68,9.63,9.65,1370.0,1322353.0 -2024-08-28 09:45:00,9.65,9.65,9.61,9.62,2150.0,2070818.0 -2024-08-28 09:50:00,9.61,9.64,9.61,9.61,1176.0,1131950.0 -2024-08-28 09:55:00,9.61,9.64,9.6,9.63,2469.0,2373771.0 -2024-08-28 10:00:00,9.64,9.65,9.62,9.63,1141.0,1099787.0 -2024-08-28 10:05:00,9.64,9.66,9.63,9.66,861.0,830158.0 -2024-08-28 10:10:00,9.66,9.69,9.66,9.68,997.0,964710.0 -2024-08-28 10:15:00,9.69,9.69,9.65,9.65,559.0,540337.0 -2024-08-28 10:20:00,9.65,9.72,9.64,9.7,1771.0,1715031.0 -2024-08-28 10:25:00,9.71,9.72,9.7,9.72,940.0,913066.0 -2024-08-28 10:30:00,9.72,9.73,9.71,9.72,2214.0,2150644.0 -2024-08-28 10:35:00,9.71,9.73,9.71,9.72,528.0,513378.0 -2024-08-28 10:40:00,9.72,9.79,9.72,9.76,1897.0,1851397.0 -2024-08-28 10:45:00,9.76,9.78,9.75,9.78,589.0,575053.0 -2024-08-28 10:50:00,9.78,9.84,9.78,9.83,4936.0,4842772.0 -2024-08-28 10:55:00,9.83,9.87,9.83,9.85,2628.0,2588449.0 -2024-08-28 11:00:00,9.84,9.85,9.81,9.82,1203.0,1182313.0 -2024-08-28 11:05:00,9.83,9.86,9.83,9.83,1411.0,1388223.0 -2024-08-28 11:10:00,9.83,9.83,9.81,9.82,309.0,303303.0 -2024-08-28 11:15:00,9.81,9.82,9.8,9.81,692.0,678656.0 -2024-08-28 11:20:00,9.8,9.81,9.79,9.79,233.0,228339.0 -2024-08-28 11:25:00,9.79,9.8,9.78,9.78,348.0,340735.0 -2024-08-28 11:30:00,9.79,9.79,9.76,9.77,790.0,772487.0 -2024-08-28 13:05:00,9.77,9.79,9.74,9.79,1043.0,1018033.0 -2024-08-28 13:10:00,9.79,9.83,9.79,9.8,1207.0,1183148.0 -2024-08-28 13:15:00,9.81,9.81,9.79,9.79,352.0,344965.0 -2024-08-28 13:20:00,9.79,9.82,9.79,9.81,880.0,862637.0 -2024-08-28 13:25:00,9.8,9.81,9.8,9.8,373.0,365601.0 -2024-08-28 13:30:00,9.8,9.82,9.79,9.81,658.0,645143.0 -2024-08-28 13:35:00,9.8,9.81,9.78,9.79,549.0,537621.0 -2024-08-28 13:40:00,9.79,9.81,9.78,9.81,473.0,463421.0 -2024-08-28 13:45:00,9.8,9.81,9.8,9.8,420.0,411721.0 -2024-08-28 13:50:00,9.8,9.83,9.8,9.82,1138.0,1117510.0 -2024-08-28 13:55:00,9.86,9.89,9.86,9.86,7478.0,7376113.0 -2024-08-28 14:00:00,9.87,9.87,9.83,9.83,1174.0,1156760.0 -2024-08-28 14:05:00,9.83,9.85,9.83,9.83,449.0,441681.0 -2024-08-28 14:10:00,9.83,9.84,9.83,9.83,244.0,239881.0 -2024-08-28 14:15:00,9.83,9.83,9.81,9.83,658.0,646477.0 -2024-08-28 14:20:00,9.82,9.84,9.82,9.82,630.0,619117.0 -2024-08-28 14:25:00,9.82,9.84,9.81,9.83,581.0,570702.0 -2024-08-28 14:30:00,9.84,9.84,9.82,9.82,648.0,636531.0 -2024-08-28 14:35:00,9.82,9.84,9.82,9.84,317.0,311511.0 -2024-08-28 14:40:00,9.84,9.85,9.83,9.84,968.0,952761.0 -2024-08-28 14:45:00,9.84,9.85,9.83,9.83,385.0,378772.0 -2024-08-28 14:50:00,9.84,9.84,9.82,9.83,646.0,635242.0 -2024-08-28 14:55:00,9.83,9.85,9.82,9.82,2189.0,2152741.0 -2024-08-28 15:00:00,9.83,9.84,9.81,9.82,2308.0,2267449.0 -2024-08-29 09:35:00,9.82,9.84,9.75,9.8,4262.0,4167116.0 -2024-08-29 09:40:00,9.8,9.81,9.77,9.8,1804.0,1765329.0 -2024-08-29 09:45:00,9.8,9.83,9.79,9.82,1056.0,1035903.0 -2024-08-29 09:50:00,9.82,9.85,9.79,9.8,1359.0,1334422.0 -2024-08-29 09:55:00,9.81,9.84,9.81,9.83,886.0,870006.0 -2024-08-29 10:00:00,9.82,9.83,9.81,9.83,934.0,917431.0 -2024-08-29 10:05:00,9.83,9.86,9.83,9.85,1196.0,1177365.0 -2024-08-29 10:10:00,9.84,9.86,9.84,9.84,930.0,916152.0 -2024-08-29 10:15:00,9.84,9.87,9.84,9.87,1256.0,1238360.0 -2024-08-29 10:20:00,9.86,9.87,9.84,9.85,1574.0,1550876.0 -2024-08-29 10:25:00,9.85,9.87,9.83,9.83,1583.0,1559557.0 -2024-08-29 10:30:00,9.83,9.84,9.82,9.82,575.0,565201.0 -2024-08-29 10:35:00,9.82,9.84,9.81,9.82,767.0,753519.0 -2024-08-29 10:40:00,9.83,9.85,9.82,9.85,815.0,801758.0 -2024-08-29 10:45:00,9.85,9.88,9.85,9.87,1169.0,1153102.0 -2024-08-29 10:50:00,9.87,9.88,9.85,9.88,1029.0,1015797.0 -2024-08-29 10:55:00,9.88,9.91,9.88,9.91,2233.0,2208715.0 -2024-08-29 11:00:00,9.91,9.91,9.88,9.89,1150.0,1137781.0 -2024-08-29 11:05:00,9.89,9.9,9.87,9.87,595.0,588109.0 -2024-08-29 11:10:00,9.87,9.87,9.85,9.85,549.0,541430.0 -2024-08-29 11:15:00,9.86,9.87,9.85,9.87,751.0,740963.0 -2024-08-29 11:20:00,9.86,9.87,9.85,9.87,437.0,430959.0 -2024-08-29 11:25:00,9.86,9.89,9.86,9.86,625.0,617074.0 -2024-08-29 11:30:00,9.87,9.89,9.87,9.88,349.0,344735.0 diff --git a/examples/get_akshare_date_2024-2025_x.py b/examples/get_akshare_date_2024-2025_x.py new file mode 100644 index 0000000..070ecf8 --- /dev/null +++ b/examples/get_akshare_date_2024-2025_x.py @@ -0,0 +1,629 @@ +import pandas as pd +import requests +import json +from datetime import datetime, timedelta +import os +import time +import random + + +def get_stock_market(stock_code): + """ + 根据股票代码判断市场类型 + 返回: 市场前缀 '0'-深交所, '1'-上交所 + """ + if stock_code.startswith(('0', '2', '3')): + return '0' # 深交所 + elif stock_code.startswith(('6', '9')): + return '1' # 上交所 + else: + return '1' # 默认上交所 + + +def get_stock_data_eastmoney(stock_code="002354", start_year=2024, end_year=2025): + """ + 使用东方财富网API获取指定年份范围的股票数据 - 修复版 + """ + try: + print(f"正在从东方财富网获取股票 {stock_code} 的 {start_year}-{end_year} 年数据...") + + # 计算日期范围 + start_date = f"{start_year}0101" + current_date = datetime.now() + + if current_date.year > end_year: + end_date = f"{end_year}1231" + else: + end_date = current_date.strftime('%Y%m%d') + + print(f"时间范围: {start_date} 到 {end_date}") + + # 获取市场类型 + market = get_stock_market(stock_code) + secid = f"{market}.{stock_code}" + + # 使用更简单的东方财富API + url = "http://push2his.eastmoney.com/api/qt/stock/kline/get" + + params = { + 'secid': secid, + 'fields1': 'f1,f2,f3,f4,f5,f6', + 'fields2': 'f51,f52,f53,f54,f55,f56,f57,f58,f59,f60,f61', + 'klt': '101', # 日线 + 'fqt': '1', # 前复权 + 'beg': start_date, + 'end': end_date, + 'lmt': '10000', + 'ut': 'fa5fd1943c7b386f172d6893dbfba10b', + 'cb': f'jQuery{random.randint(1000000, 9999999)}_{int(time.time()*1000)}' + } + + headers = { + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36', + 'Referer': 'https://quote.eastmoney.com/', + 'Accept': '*/*', + } + + time.sleep(random.uniform(1, 2)) + + response = requests.get(url, params=params, headers=headers, timeout=10) + + print(f"API响应状态码: {response.status_code}") + + if response.status_code == 200: + # 处理JSONP响应 + response_text = response.text + + # 提取JSON数据(处理JSONP格式) + if response_text.startswith('/**/'): + response_text = response_text[4:] + + # 查找JSON数据的开始和结束位置 + start_idx = response_text.find('(') + end_idx = response_text.rfind(')') + + if start_idx != -1 and end_idx != -1: + json_str = response_text[start_idx + 1:end_idx] + try: + data = json.loads(json_str) + except json.JSONDecodeError: + print("❌ JSON解析失败,尝试直接解析...") + # 如果JSON解析失败,尝试直接提取数据 + return parse_kline_data_directly(response_text, stock_code, start_year, end_year) + else: + print("❌ 无法找到JSON数据边界") + return None + + print(f"API返回数据状态: {data.get('rc', 'N/A')}") + + if data and data.get('data') is not None: + klines = data['data'].get('klines', []) + print(f"获取到 {len(klines)} 条K线数据") + + if not klines: + print("⚠️ K线数据为空") + return None + + # 解析数据 + stock_data = [] + for kline in klines: + try: + items = kline.split(',') + if len(items) >= 6: + stock_data.append({ + '日期': items[0], + '股票代码': stock_code, + '开盘价': float(items[1]), + '收盘价': float(items[2]), + '最高价': float(items[3]), + '最低价': float(items[4]), + '成交量': float(items[5]), + '成交额': float(items[6]) if len(items) > 6 else 0, + '振幅': float(items[7]) if len(items) > 7 else 0, + '涨跌幅': float(items[8]) if len(items) > 8 else 0, + '涨跌额': float(items[9]) if len(items) > 9 else 0, + '换手率': float(items[10]) if len(items) > 10 else 0 + }) + except (ValueError, IndexError) as e: + continue + + if not stock_data: + print("❌ 解析后无有效数据") + return None + + df = pd.DataFrame(stock_data) + df['日期'] = pd.to_datetime(df['日期']) + df.set_index('日期', inplace=True) + df = df.sort_index() + + # 筛选指定年份的数据 + df = df[(df.index.year >= start_year) & (df.index.year <= end_year)] + + print(f"✅ 成功获取 {len(df)} 条有效数据") + print(f"实际时间范围: {df.index.min().strftime('%Y-%m-%d')} 到 {df.index.max().strftime('%Y-%m-%d')}") + return df + else: + print("❌ API返回数据为空") + return None + else: + print(f"❌ 请求失败,状态码: {response.status_code}") + return None + + except Exception as e: + print(f"❌ 获取数据时出错: {str(e)}") + return None + + +def parse_kline_data_directly(response_text, stock_code, start_year, end_year): + """ + 直接解析K线数据(当JSON解析失败时使用) + """ + try: + # 尝试直接从响应文本中提取K线数据 + if '"klines":[' in response_text: + start_idx = response_text.find('"klines":[') + 10 + end_idx = response_text.find(']', start_idx) + klines_str = response_text[start_idx:end_idx] + + # 清理字符串并分割 + klines = klines_str.replace('"', '').split(',') + + stock_data = [] + for kline in klines: + if kline.strip(): + items = kline.split(',') + if len(items) >= 6: + stock_data.append({ + '日期': items[0], + '股票代码': stock_code, + '开盘价': float(items[1]), + '收盘价': float(items[2]), + '最高价': float(items[3]), + '最低价': float(items[4]), + '成交量': float(items[5]), + '成交额': float(items[6]) if len(items) > 6 else 0, + }) + + if stock_data: + df = pd.DataFrame(stock_data) + df['日期'] = pd.to_datetime(df['日期']) + df.set_index('日期', inplace=True) + df = df.sort_index() + df = df[(df.index.year >= start_year) & (df.index.year <= end_year)] + print(f"✅ 直接解析获取 {len(df)} 条数据") + return df + except Exception as e: + print(f"❌ 直接解析也失败: {e}") + + return None + + +def get_stock_data_akshare(stock_code="002354", start_year=2024, end_year=2025): + """ + 使用AKShare作为备用数据源 - 修复版 + """ + try: + print(f"尝试使用AKShare获取股票 {stock_code} 数据...") + import akshare as ak + + # 计算日期范围 + start_date = f"{start_year}0101" + end_date = datetime.now().strftime('%Y%m%d') + + # 获取数据 + df = ak.stock_zh_a_hist(symbol=stock_code, period="daily", + start_date=start_date, end_date=end_date, + adjust="qfq") + + if df is not None and not df.empty: + # 重命名列以匹配我们的格式 + column_mapping = { + '日期': '日期', + '开盘': '开盘价', + '收盘': '收盘价', + '最高': '最高价', + '最低': '最低价', + '成交量': '成交量', + '成交额': '成交额', + '振幅': '振幅', + '涨跌幅': '涨跌幅', + '涨跌额': '涨跌额', + '换手率': '换手率' + } + + # 只映射存在的列 + actual_mapping = {k: v for k, v in column_mapping.items() if k in df.columns} + df = df.rename(columns=actual_mapping) + + # 添加股票代码列 + df['股票代码'] = stock_code + df['日期'] = pd.to_datetime(df['日期']) + df.set_index('日期', inplace=True) + df = df.sort_index() + + # 筛选指定年份 + df = df[(df.index.year >= start_year) & (df.index.year <= end_year)] + + print(f"✅ AKShare成功获取 {len(df)} 条数据") + return df + else: + print("❌ AKShare未返回数据") + return None + + except ImportError: + print("⚠️ AKShare未安装,使用 pip install akshare 安装") + return None + except Exception as e: + print(f"❌ AKShare获取数据失败: {e}") + return None + + +def get_stock_data_baostock(stock_code="002354", start_year=2024, end_year=2025): + """ + 使用Baostock作为第三个数据源 + """ + try: + print(f"尝试使用Baostock获取股票 {stock_code} 数据...") + import baostock as bs + import pandas as pd + + # 登录系统 + lg = bs.login() + + # 计算日期范围 + start_date = f"{start_year}-01-01" + end_date = datetime.now().strftime('%Y-%m-%d') + + # 根据市场添加前缀 + market = get_stock_market(stock_code) + if market == '0': + full_code = f"sz.{stock_code}" + else: + full_code = f"sh.{stock_code}" + + # 获取数据 + rs = bs.query_history_k_data_plus( + full_code, + "date,open,high,low,close,volume,amount,turn,pctChg", + start_date=start_date, + end_date=end_date, + frequency="d", + adjustflag="2" # 前复权 + ) + + data_list = [] + while (rs.error_code == '0') & rs.next(): + data_list.append(rs.get_row_data()) + + # 退出系统 + bs.logout() + + if data_list: + df = pd.DataFrame(data_list, columns=rs.fields) + + # 数据类型转换 + df['date'] = pd.to_datetime(df['date']) + df['open'] = pd.to_numeric(df['open']) + df['high'] = pd.to_numeric(df['high']) + df['low'] = pd.to_numeric(df['low']) + df['close'] = pd.to_numeric(df['close']) + df['volume'] = pd.to_numeric(df['volume']) + df['amount'] = pd.to_numeric(df['amount']) + df['turn'] = pd.to_numeric(df['turn']) + df['pctChg'] = pd.to_numeric(df['pctChg']) + + # 重命名列 + df = df.rename(columns={ + 'date': '日期', + 'open': '开盘价', + 'high': '最高价', + 'low': '最低价', + 'close': '收盘价', + 'volume': '成交量', + 'amount': '成交额', + 'turn': '换手率', + 'pctChg': '涨跌幅' + }) + + # 添加股票代码列 + df['股票代码'] = stock_code + df.set_index('日期', inplace=True) + df = df.sort_index() + + # 筛选指定年份 + df = df[(df.index.year >= start_year) & (df.index.year <= end_year)] + + # 计算涨跌额 + df['涨跌额'] = df['收盘价'].diff() + + print(f"✅ Baostock成功获取 {len(df)} 条数据") + return df + else: + print("❌ Baostock未返回数据") + return None + + except ImportError: + print("⚠️ Baostock未安装,使用 pip install baostock 安装") + return None + except Exception as e: + print(f"❌ Baostock获取数据失败: {e}") + return None + + +def get_stock_data_with_retry(stock_code="002354", start_year=2024, end_year=2025, retry_count=2): + """ + 带重试机制的数据获取 - 多数据源版本 + """ + data_sources = [ + ("AKShare", get_stock_data_akshare), + ("Baostock", get_stock_data_baostock), + ("东方财富", get_stock_data_eastmoney) + ] + + for source_name, data_func in data_sources: + print(f"\n🔍 尝试从 {source_name} 获取数据...") + data = data_func(stock_code, start_year, end_year) + + if data is not None and not data.empty: + # 检查数据是否包含目标年份 + available_years = data.index.year.unique() + print(f"获取到的数据年份: {sorted(available_years)}") + + if any(year in available_years for year in range(start_year, end_year + 1)): + print(f"✅ {source_name} 数据获取成功!") + # 标记数据来源 + data.attrs['data_source'] = source_name + return data + else: + print(f"⚠️ 数据未包含目标年份数据") + + print("❌ 所有真实数据源都失败,使用示例数据...") + return create_sample_data(stock_code, start_year, end_year) + + +def create_sample_data(stock_code="002354", start_year=2024, end_year=2025): + """ + 创建更真实的示例数据 + """ + print(f"📊 创建 {start_year}-{end_year} 年的示例数据...") + + # 生成交易日(排除周末) + start_date = datetime(start_year, 1, 1) + end_date = datetime.now() + all_dates = pd.bdate_range(start=start_date, end=end_date, freq='B') + + # 只保留目标年份的数据 + trading_dates = [date for date in all_dates if start_year <= date.year <= end_year] + + # 生成更真实的股价数据 + import numpy as np + np.random.seed(42) + + # 设置合理的基准价格 + base_prices = { + '600580': 12.0, # 卧龙电驱 - 更合理的价格 + '002354': 5.0, # 天娱数科 + '300207': 15.0, # 欣旺达 + } + base_price = base_prices.get(stock_code, 10.0) + + stock_data = [] + current_price = base_price + + for i, date in enumerate(trading_dates): + # 更真实的股价波动 + volatility = 0.015 # 1.5%的日波动率 + + if i > 0: + # 使用更真实的随机游走 + daily_return = np.random.normal(0, volatility) + # 添加一些趋势 + if i < len(trading_dates) * 0.3: # 前30%的时间 + trend_bias = 0.0005 # 轻微上涨趋势 + elif i < len(trading_dates) * 0.7: # 中间40%的时间 + trend_bias = -0.0003 # 轻微下跌趋势 + else: # 后30%的时间 + trend_bias = 0.0002 # 轻微上涨趋势 + + daily_return += trend_bias + current_price = current_price * (1 + daily_return) + + # 价格边界限制 - 更合理 + current_price = max(base_price * 0.5, min(base_price * 2.0, current_price)) + else: + current_price = base_price + + # 生成OHLC数据 + open_variation = np.random.normal(0, volatility * 0.2) + open_price = current_price * (1 + open_variation) + + daily_range = abs(np.random.normal(volatility * 0.8, volatility * 0.3)) + high_price = max(open_price, current_price) * (1 + daily_range) + low_price = min(open_price, current_price) * (1 - daily_range) + close_price = current_price + + # 确保价格合理性 + high_price = max(open_price, close_price, low_price, high_price) + low_price = min(open_price, close_price, high_price, low_price) + + # 生成成交量(更合理) + base_volume = 500000 # 基础成交量 + volume_variation = abs(daily_return) * 3000000 if i > 0 else 0 + volume = int(base_volume + volume_variation + np.random.randint(-100000, 200000)) + volume = max(100000, volume) + + # 计算成交额(万元) + amount = volume * close_price / 10000 + + # 计算涨跌幅和涨跌额 + if i > 0: + prev_close = stock_data[-1]['收盘价'] + price_change = close_price - prev_close + pct_change = (price_change / prev_close) * 100 + else: + price_change = 0 + pct_change = 0 + + # 计算振幅 + amplitude = ((high_price - low_price) / open_price) * 100 + + # 生成换手率(0.5%-8%之间) + turnover_rate = np.random.uniform(0.5, 8.0) + + stock_data.append({ + '日期': date, + '股票代码': stock_code, + '开盘价': round(open_price, 2), + '收盘价': round(close_price, 2), + '最高价': round(high_price, 2), + '最低价': round(low_price, 2), + '成交量': volume, + '成交额': round(amount, 2), + '振幅': round(amplitude, 2), + '涨跌幅': round(pct_change, 2), + '涨跌额': round(price_change, 2), + '换手率': round(turnover_rate, 2) + }) + + df = pd.DataFrame(stock_data) + df.set_index('日期', inplace=True) + + print(f"✅ 已创建 {len(df)} 条 {start_year}-{end_year} 年的模拟数据") + print(f"时间范围: {df.index.min().strftime('%Y-%m-%d')} 到 {df.index.max().strftime('%Y-%m-%d')}") + + # 标记为模拟数据 + df.attrs['data_source'] = '模拟数据' + + return df + + +def display_data_info(df, stock_code, start_year, end_year): + """显示数据信息""" + if df is None or df.empty: + print("没有数据可显示") + return + + # 获取数据来源 + data_source = df.attrs.get('data_source', '未知来源') + + print(f"\n{'=' * 60}") + print(f"股票 {stock_code} {start_year}-{end_year} 年数据摘要") + print(f"{'=' * 60}") + + print(f"数据时间范围: {df.index.min().strftime('%Y-%m-%d')} 到 {df.index.max().strftime('%Y-%m-%d')}") + print(f"总交易天数: {len(df)}") + print(f"数据来源: {data_source}") + + # 按年份显示统计 + for year in sorted(df.index.year.unique()): + year_data = df[df.index.year == year] + print(f"\n{year}年统计:") + print(f" 交易天数: {len(year_data)}") + print(f" 平均收盘价: {year_data['收盘价'].mean():.2f} 元") + print(f" 最高价: {year_data['最高价'].max():.2f} 元") + print(f" 最低价: {year_data['最低价'].min():.2f} 元") + if len(year_data) > 1: + year_return = (year_data['收盘价'].iloc[-1] / year_data['收盘价'].iloc[0] - 1) * 100 + print(f" 年度涨跌幅: {year_return:+.2f}%") + + # 显示最新交易日数据 + latest_date = df.index.max() + print(f"\n最新交易日 ({latest_date.strftime('%Y-%m-%d')}) 数据:") + latest_data = df.loc[latest_date] + for col, value in latest_data.items(): + if col != '股票代码': + if col in ['成交量']: + print(f" {col}: {value:,.0f}") + elif col in ['成交额']: + print(f" {col}: {value:,.2f} 万元") + else: + print(f" {col}: {value}") + + +def save_stock_data(df, stock_code, save_dir="D:/lianghuajiaoyi/Kronos/examples/data"): + """ + 保存股票数据到指定目录 + """ + if df is not None and not df.empty: + # 确保保存目录存在 + os.makedirs(save_dir, exist_ok=True) + + # 保存CSV文件 + csv_file = os.path.join(save_dir, f"{stock_code}_stock_data.csv") + + # 重置索引以便保存日期列 + df_reset = df.reset_index() + df_reset.to_csv(csv_file, encoding='utf-8-sig', index=False) + + print(f"\n📁 股票数据已保存: {csv_file}") + return True + return False + + +def main(stock_code="002354", start_year=2024, end_year=2025): + """ + 主函数:获取并保存股票数据 - 最终版 + """ + # 设置保存目录 + save_directory = "D:/lianghuajiaoyi/Kronos/examples/data" + + print("=" * 60) + print(f"开始获取股票 {stock_code} 的 {start_year}-{end_year} 年数据") + print("=" * 60) + print(f"数据将保存到: {save_directory}") + + # 检查必要库 + try: + import requests + import numpy as np + except ImportError: + print("正在安装必要库...") + import subprocess + subprocess.check_call(["pip", "install", "requests", "numpy", "pandas"]) + import requests + import numpy as np + + # 获取数据(多数据源) + stock_data = get_stock_data_with_retry(stock_code, start_year, end_year) + + if stock_data is not None: + # 显示数据信息 + display_data_info(stock_data, stock_code, start_year, end_year) + + # 保存数据到指定目录 + save_stock_data(stock_data, stock_code, save_directory) + + print(f"\n🎉 股票 {stock_code} 数据处理完成!") + print(f"最新数据日期: {stock_data.index.max().strftime('%Y-%m-%d')}") + + # 显示保存的文件 + csv_file = os.path.join(save_directory, f"{stock_code}_stock_data.csv") + if os.path.exists(csv_file): + file_size = os.path.getsize(csv_file) / 1024 # KB + print(f"📄 生成的文件: {csv_file} ({file_size:.1f} KB)") + else: + print("❌ 未能获取股票数据") + + +# 使用方法说明 +if __name__ == "__main__": + """ + 使用方法: + 修改下面的参数来获取不同股票的数据 + """ + + # ==================== 在这里修改参数 ==================== + TARGET_STOCK_CODE = "300418" # 股票代码 + START_YEAR = 2024 # 开始年份 + END_YEAR = 2025 # 结束年份 + # ===================================================== + + print("股票数据获取工具 - 终极优化版") + print("说明:修改代码中的 TARGET_STOCK_CODE 来获取不同股票的数据") + print(f"当前设置: 股票代码={TARGET_STOCK_CODE}, 年份范围={START_YEAR}-{END_YEAR}") + print() + + # 运行主程序 + main(stock_code=TARGET_STOCK_CODE, start_year=START_YEAR, end_year=END_YEAR) + + print(f"\n💡 提示:要获取其他股票数据,请修改代码中的 TARGET_STOCK_CODE 变量") \ No newline at end of file diff --git a/examples/get_date_new.py b/examples/get_date_new.py new file mode 100644 index 0000000..2819960 --- /dev/null +++ b/examples/get_date_new.py @@ -0,0 +1,661 @@ +import pandas as pd +import requests +import json +from datetime import datetime, timedelta +import os +import time +import random + + +def get_stock_market(stock_code): + """ + 根据股票代码判断市场类型 + 返回: 市场前缀 '0'-深交所, '1'-上交所 + """ + if stock_code.startswith(('0', '2', '3')): + return '0' # 深交所 + elif stock_code.startswith(('6', '9')): + return '1' # 上交所 + else: + return '1' # 默认上交所 + + +def get_stock_data_eastmoney_all_history(stock_code="002354"): + """ + 使用东方财富网API获取股票所有历史数据 + """ + try: + print(f"正在从东方财富网获取股票 {stock_code} 的全部历史数据...") + + # 获取市场类型 + market = get_stock_market(stock_code) + secid = f"{market}.{stock_code}" + + # 使用东方财富API获取所有历史数据 + url = "http://push2his.eastmoney.com/api/qt/stock/kline/get" + + # 设置足够早的起始日期(中国股市从1990年开始) + start_date = "19900101" + end_date = datetime.now().strftime('%Y%m%d') + + params = { + 'secid': secid, + 'fields1': 'f1,f2,f3,f4,f5,f6', + 'fields2': 'f51,f52,f53,f54,f55,f56,f57,f58,f59,f60,f61', + 'klt': '101', # 日线 + 'fqt': '1', # 前复权 + 'beg': start_date, + 'end': end_date, + 'lmt': '50000', # 增加限制数量以获取更多历史数据 + 'ut': 'fa5fd1943c7b386f172d6893dbfba10b', + 'cb': f'jQuery{random.randint(1000000, 9999999)}_{int(time.time() * 1000)}' + } + + headers = { + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36', + 'Referer': 'https://quote.eastmoney.com/', + 'Accept': '*/*', + } + + time.sleep(random.uniform(1, 2)) + + response = requests.get(url, params=params, headers=headers, timeout=15) + + print(f"API响应状态码: {response.status_code}") + + if response.status_code == 200: + # 处理JSONP响应 + response_text = response.text + + # 提取JSON数据(处理JSONP格式) + if response_text.startswith('/**/'): + response_text = response_text[4:] + + # 查找JSON数据的开始和结束位置 + start_idx = response_text.find('(') + end_idx = response_text.rfind(')') + + if start_idx != -1 and end_idx != -1: + json_str = response_text[start_idx + 1:end_idx] + try: + data = json.loads(json_str) + except json.JSONDecodeError: + print("❌ JSON解析失败,尝试直接解析...") + return parse_kline_data_directly_all_history(response_text, stock_code) + else: + print("❌ 无法找到JSON数据边界") + return None + + print(f"API返回数据状态: {data.get('rc', 'N/A')}") + + if data and data.get('data') is not None: + klines = data['data'].get('klines', []) + print(f"获取到 {len(klines)} 条历史K线数据") + + if not klines: + print("⚠️ K线数据为空") + return None + + # 解析数据 + stock_data = [] + for kline in klines: + try: + items = kline.split(',') + if len(items) >= 6: + stock_data.append({ + '日期': items[0], + '股票代码': stock_code, + '开盘价': float(items[1]), + '收盘价': float(items[2]), + '最高价': float(items[3]), + '最低价': float(items[4]), + '成交量': float(items[5]), + '成交额': float(items[6]) if len(items) > 6 else 0, + '振幅': float(items[7]) if len(items) > 7 else 0, + '涨跌幅': float(items[8]) if len(items) > 8 else 0, + '涨跌额': float(items[9]) if len(items) > 9 else 0, + '换手率': float(items[10]) if len(items) > 10 else 0 + }) + except (ValueError, IndexError) as e: + continue + + if not stock_data: + print("❌ 解析后无有效数据") + return None + + df = pd.DataFrame(stock_data) + df['日期'] = pd.to_datetime(df['日期']) + df.set_index('日期', inplace=True) + df = df.sort_index() + + print(f"✅ 成功获取 {len(df)} 条历史数据") + print( + f"历史数据时间范围: {df.index.min().strftime('%Y-%m-%d')} 到 {df.index.max().strftime('%Y-%m-%d')}") + return df + else: + print("❌ API返回数据为空") + return None + else: + print(f"❌ 请求失败,状态码: {response.status_code}") + return None + + except Exception as e: + print(f"❌ 获取历史数据时出错: {str(e)}") + return None + + +def parse_kline_data_directly_all_history(response_text, stock_code): + """ + 直接解析K线数据(当JSON解析失败时使用)- 全历史版本 + """ + try: + # 尝试直接从响应文本中提取K线数据 + if '"klines":[' in response_text: + start_idx = response_text.find('"klines":[') + 10 + end_idx = response_text.find(']', start_idx) + klines_str = response_text[start_idx:end_idx] + + # 清理字符串并分割 + klines = [k.strip().strip('"') for k in klines_str.split('","') if k.strip()] + + stock_data = [] + for kline in klines: + if kline.strip(): + items = kline.split(',') + if len(items) >= 6: + stock_data.append({ + '日期': items[0], + '股票代码': stock_code, + '开盘价': float(items[1]), + '收盘价': float(items[2]), + '最高价': float(items[3]), + '最低价': float(items[4]), + '成交量': float(items[5]), + '成交额': float(items[6]) if len(items) > 6 else 0, + }) + + if stock_data: + df = pd.DataFrame(stock_data) + df['日期'] = pd.to_datetime(df['日期']) + df.set_index('日期', inplace=True) + df = df.sort_index() + print(f"✅ 直接解析获取 {len(df)} 条历史数据") + return df + except Exception as e: + print(f"❌ 直接解析也失败: {e}") + + return None + + +def get_stock_data_akshare_all_history(stock_code="002354"): + """ + 使用AKShare作为备用数据源 - 全历史版本 + """ + try: + print(f"尝试使用AKShare获取股票 {stock_code} 全部历史数据...") + import akshare as ak + + # 获取所有历史数据 + df = ak.stock_zh_a_hist(symbol=stock_code, period="daily", + adjust="qfq") + + if df is not None and not df.empty: + # 重命名列以匹配我们的格式 + column_mapping = { + '日期': '日期', + '开盘': '开盘价', + '收盘': '收盘价', + '最高': '最高价', + '最低': '最低价', + '成交量': '成交量', + '成交额': '成交额', + '振幅': '振幅', + '涨跌幅': '涨跌幅', + '涨跌额': '涨跌额', + '换手率': '换手率' + } + + # 只映射存在的列 + actual_mapping = {k: v for k, v in column_mapping.items() if k in df.columns} + df = df.rename(columns=actual_mapping) + + # 添加股票代码列 + df['股票代码'] = stock_code + df['日期'] = pd.to_datetime(df['日期']) + df.set_index('日期', inplace=True) + df = df.sort_index() + + print(f"✅ AKShare成功获取 {len(df)} 条历史数据") + print(f"时间范围: {df.index.min().strftime('%Y-%m-%d')} 到 {df.index.max().strftime('%Y-%m-%d')}") + return df + else: + print("❌ AKShare未返回数据") + return None + + except ImportError: + print("⚠️ AKShare未安装,使用 pip install akshare 安装") + return None + except Exception as e: + print(f"❌ AKShare获取历史数据失败: {e}") + return None + + +def get_stock_data_baostock_all_history(stock_code="002354"): + """ + 使用Baostock作为第三个数据源 - 全历史版本 + """ + try: + print(f"尝试使用Baostock获取股票 {stock_code} 全部历史数据...") + import baostock as bs + import pandas as pd + + # 登录系统 + lg = bs.login() + + # 根据市场添加前缀 + market = get_stock_market(stock_code) + if market == '0': + full_code = f"sz.{stock_code}" + else: + full_code = f"sh.{stock_code}" + + # 获取上市日期 + rs = bs.query_stock_basic(code=full_code) + if rs.error_code != '0': + print(f"❌ 获取股票基本信息失败: {rs.error_msg}") + bs.logout() + return None + + # 获取上市日期 + list_date = None + while (rs.error_code == '0') & rs.next(): + list_date = rs.get_row_data()[2] # 上市日期在第三个字段 + + if not list_date: + print("❌ 无法获取上市日期") + bs.logout() + return None + + print(f"股票上市日期: {list_date}") + + # 获取从上市日期到现在的所有数据 + end_date = datetime.now().strftime('%Y-%m-%d') + + # 获取数据 + rs = bs.query_history_k_data_plus( + full_code, + "date,open,high,low,close,volume,amount,turn,pctChg", + start_date=list_date, + end_date=end_date, + frequency="d", + adjustflag="2" # 前复权 + ) + + data_list = [] + while (rs.error_code == '0') & rs.next(): + data_list.append(rs.get_row_data()) + + # 退出系统 + bs.logout() + + if data_list: + df = pd.DataFrame(data_list, columns=rs.fields) + + # 数据类型转换 + df['date'] = pd.to_datetime(df['date']) + df['open'] = pd.to_numeric(df['open'], errors='coerce') + df['high'] = pd.to_numeric(df['high'], errors='coerce') + df['low'] = pd.to_numeric(df['low'], errors='coerce') + df['close'] = pd.to_numeric(df['close'], errors='coerce') + df['volume'] = pd.to_numeric(df['volume'], errors='coerce') + df['amount'] = pd.to_numeric(df['amount'], errors='coerce') + df['turn'] = pd.to_numeric(df['turn'], errors='coerce') + df['pctChg'] = pd.to_numeric(df['pctChg'], errors='coerce') + + # 重命名列 + df = df.rename(columns={ + 'date': '日期', + 'open': '开盘价', + 'high': '最高价', + 'low': '最低价', + 'close': '收盘价', + 'volume': '成交量', + 'amount': '成交额', + 'turn': '换手率', + 'pctChg': '涨跌幅' + }) + + # 添加股票代码列 + df['股票代码'] = stock_code + df.set_index('日期', inplace=True) + df = df.sort_index() + + # 计算涨跌额 + df['涨跌额'] = df['收盘价'].diff() + + # 清理无效数据 + df = df.dropna() + + print(f"✅ Baostock成功获取 {len(df)} 条历史数据") + print(f"时间范围: {df.index.min().strftime('%Y-%m-%d')} 到 {df.index.max().strftime('%Y-%m-%d')}") + return df + else: + print("❌ Baostock未返回数据") + return None + + except ImportError: + print("⚠️ Baostock未安装,使用 pip install baostock 安装") + return None + except Exception as e: + print(f"❌ Baostock获取历史数据失败: {e}") + return None + + +def get_stock_data_with_retry_all_history(stock_code="002354", retry_count=2): + """ + 带重试机制的数据获取 - 多数据源全历史版本 + """ + data_sources = [ + ("AKShare", get_stock_data_akshare_all_history), + ("Baostock", get_stock_data_baostock_all_history), + ("东方财富", get_stock_data_eastmoney_all_history) + ] + + for source_name, data_func in data_sources: + print(f"\n🔍 尝试从 {source_name} 获取全部历史数据...") + data = data_func(stock_code) + + if data is not None and not data.empty: + print(f"✅ {source_name} 历史数据获取成功!") + # 标记数据来源 + data.attrs['data_source'] = source_name + return data + + print("❌ 所有真实数据源都失败,使用示例数据...") + return create_sample_data_all_history(stock_code) + + +def create_sample_data_all_history(stock_code="002354"): + """ + 创建更真实的历史示例数据 - 从上市年份开始 + """ + # 模拟不同股票的上市年份 + list_years = { + '600580': 2002, # 卧龙电驱 + '002354': 2010, # 天娱数科 + '300418': 2015, # 昆仑万维 + '300207': 2011, # 欣旺达 + } + + list_year = list_years.get(stock_code, 2010) + current_year = datetime.now().year + + print(f"📊 创建 {stock_code} 从 {list_year} 年上市至今的示例数据...") + + # 生成从上市年份到现在的交易日(排除周末) + start_date = datetime(list_year, 1, 1) + end_date = datetime.now() + all_dates = pd.bdate_range(start=start_date, end=end_date, freq='B') + + # 生成更真实的股价数据 + import numpy as np + np.random.seed(42) + + # 设置合理的基准价格(根据股票类型) + base_prices = { + '600580': 8.0, # 卧龙电驱 + '002354': 15.0, # 天娱数科 - 上市时价格较高 + '300418': 20.0, # 昆仑万维 + '300207': 12.0, # 欣旺达 + } + base_price = base_prices.get(stock_code, 10.0) + + stock_data = [] + current_price = base_price + + for i, date in enumerate(all_dates): + # 模拟真实的市场波动 + volatility = 0.02 # 2%的日波动率 + + if i > 0: + # 使用随机游走模拟价格变化 + daily_return = np.random.normal(0, volatility) + + # 模拟不同年份的市场趋势 + year = date.year + if year <= list_year + 2: # 上市初期波动较大 + daily_return += np.random.normal(0.001, 0.01) + elif year <= list_year + 5: # 成长期 + daily_return += np.random.normal(0.0005, 0.005) + else: # 成熟期 + daily_return += np.random.normal(0.0002, 0.003) + + current_price = current_price * (1 + daily_return) + + # 价格边界限制 + current_price = max(base_price * 0.3, min(base_price * 10.0, current_price)) + else: + current_price = base_price + + # 生成OHLC数据 + open_variation = np.random.normal(0, volatility * 0.2) + open_price = current_price * (1 + open_variation) + + daily_range = abs(np.random.normal(volatility * 0.8, volatility * 0.3)) + high_price = max(open_price, current_price) * (1 + daily_range) + low_price = min(open_price, current_price) * (1 - daily_range) + close_price = current_price + + # 确保价格合理性 + high_price = max(open_price, close_price, low_price, high_price) + low_price = min(open_price, close_price, high_price, low_price) + + # 生成成交量(随年份增长) + base_volume = 100000 + (year - list_year) * 50000 # 成交量逐年增长 + volume_variation = abs(daily_return) * 5000000 if i > 0 else 0 + volume = int(base_volume + volume_variation + np.random.randint(-200000, 400000)) + volume = max(50000, volume) + + # 计算成交额(万元) + amount = volume * close_price / 10000 + + # 计算涨跌幅和涨跌额 + if i > 0: + prev_close = stock_data[-1]['收盘价'] + price_change = close_price - prev_close + pct_change = (price_change / prev_close) * 100 + else: + price_change = 0 + pct_change = 0 + + # 计算振幅 + amplitude = ((high_price - low_price) / open_price) * 100 + + # 生成换手率(1%-15%之间) + turnover_rate = np.random.uniform(1.0, 15.0) + + stock_data.append({ + '日期': date, + '股票代码': stock_code, + '开盘价': round(open_price, 2), + '收盘价': round(close_price, 2), + '最高价': round(high_price, 2), + '最低价': round(low_price, 2), + '成交量': volume, + '成交额': round(amount, 2), + '振幅': round(amplitude, 2), + '涨跌幅': round(pct_change, 2), + '涨跌额': round(price_change, 2), + '换手率': round(turnover_rate, 2) + }) + + df = pd.DataFrame(stock_data) + df.set_index('日期', inplace=True) + + print(f"✅ 已创建 {len(df)} 条从 {list_year} 年至今的模拟历史数据") + print(f"时间范围: {df.index.min().strftime('%Y-%m-%d')} 到 {df.index.max().strftime('%Y-%m-%d')}") + + # 标记为模拟数据 + df.attrs['data_source'] = '模拟历史数据' + + return df + + +def display_all_history_data_info(df, stock_code): + """显示全历史数据信息""" + if df is None or df.empty: + print("没有数据可显示") + return + + # 获取数据来源 + data_source = df.attrs.get('data_source', '未知来源') + + print(f"\n{'=' * 60}") + print(f"股票 {stock_code} 全部历史数据摘要") + print(f"{'=' * 60}") + + print(f"数据时间范围: {df.index.min().strftime('%Y-%m-%d')} 到 {df.index.max().strftime('%Y-%m-%d')}") + print(f"总交易天数: {len(df):,}") + print(f"数据来源: {data_source}") + + # 按年份显示统计 + years = sorted(df.index.year.unique()) + print(f"\n历史年份: {years}") + + # 显示关键年份统计 + key_years = [years[0]] # 上市年份 + if len(years) > 1: + key_years.append(years[-1]) # 最新年份 + if len(years) > 5: + key_years.extend([years[len(years) // 2], years[len(years) // 4], years[3 * len(years) // 4]]) + + for year in sorted(set(key_years)): + year_data = df[df.index.year == year] + if len(year_data) > 0: + print(f"\n{year}年统计:") + print(f" 交易天数: {len(year_data)}") + print(f" 平均收盘价: {year_data['收盘价'].mean():.2f} 元") + print(f" 最高价: {year_data['最高价'].max():.2f} 元") + print(f" 最低价: {year_data['最低价'].min():.2f} 元") + if len(year_data) > 1: + year_return = (year_data['收盘价'].iloc[-1] / year_data['收盘价'].iloc[0] - 1) * 100 + print(f" 年度涨跌幅: {year_return:+.2f}%") + + # 显示整体统计 + print(f"\n整体统计:") + total_return = (df['收盘价'].iloc[-1] / df['收盘价'].iloc[0] - 1) * 100 + print(f" 总涨跌幅: {total_return:+.2f}%") + print(f" 历史最高价: {df['最高价'].max():.2f} 元") + print(f" 历史最低价: {df['最低价'].min():.2f} 元") + print(f" 平均日成交量: {df['成交量'].mean():,.0f} 股") + + # 显示最新交易日数据 + latest_date = df.index.max() + print(f"\n最新交易日 ({latest_date.strftime('%Y-%m-%d')}) 数据:") + latest_data = df.loc[latest_date] + for col, value in latest_data.items(): + if col != '股票代码': + if col in ['成交量']: + print(f" {col}: {value:,.0f}") + elif col in ['成交额']: + print(f" {col}: {value:,.2f} 万元") + else: + print(f" {col}: {value}") + + +def save_all_history_stock_data(df, stock_code, save_dir="D:/lianghuajiaoyi/Kronos/examples/data"): + """ + 保存全历史股票数据到指定目录 + """ + if df is not None and not df.empty: + # 确保保存目录存在 + os.makedirs(save_dir, exist_ok=True) + + # 保存CSV文件 - 使用全历史命名 + csv_file = os.path.join(save_dir, f"{stock_code}_all_history.csv") + + # 重置索引以便保存日期列 + df_reset = df.reset_index() + df_reset.to_csv(csv_file, encoding='utf-8-sig', index=False) + + print(f"\n📁 全历史股票数据已保存: {csv_file}") + + # 同时保存一个按年份分割的版本 + years = df_reset['日期'].dt.year.unique() + for year in years: + year_data = df_reset[df_reset['日期'].dt.year == year] + year_file = os.path.join(save_dir, f"{stock_code}_{year}.csv") + year_data.to_csv(year_file, encoding='utf-8-sig', index=False) + + print(f"📁 同时保存了 {len(years)} 个年份的单独数据文件") + return True + return False + + +def main_all_history(stock_code="002354"): + """ + 主函数:获取并保存股票全历史数据 + """ + # 设置保存目录 + save_directory = "D:/lianghuajiaoyi/Kronos/examples/data" + + print("=" * 60) + print(f"开始获取股票 {stock_code} 的全部历史数据") + print("=" * 60) + print(f"数据将保存到: {save_directory}") + + # 检查必要库 + try: + import requests + import numpy as np + except ImportError: + print("正在安装必要库...") + import subprocess + subprocess.check_call(["pip", "install", "requests", "numpy", "pandas"]) + import requests + import numpy as np + + # 获取全历史数据(多数据源) + stock_data = get_stock_data_with_retry_all_history(stock_code) + + if stock_data is not None: + # 显示数据信息 + display_all_history_data_info(stock_data, stock_code) + + # 保存全历史数据到指定目录 + save_all_history_stock_data(stock_data, stock_code, save_directory) + + print(f"\n🎉 股票 {stock_code} 全历史数据处理完成!") + print( + f"数据时间跨度: {stock_data.index.min().strftime('%Y-%m-%d')} 到 {stock_data.index.max().strftime('%Y-%m-%d')}") + print(f"总交易天数: {len(stock_data):,}") + + # 显示保存的文件 + csv_file = os.path.join(save_directory, f"{stock_code}_all_history.csv") + if os.path.exists(csv_file): + file_size = os.path.getsize(csv_file) / 1024 # KB + print(f"📄 生成的文件: {csv_file} ({file_size:.1f} KB)") + else: + print("❌ 未能获取股票全历史数据") + + +# 使用方法说明 +if __name__ == "__main__": + """ + 使用方法: + 修改下面的参数来获取不同股票的全历史数据 + """ + + # ==================== 在这里修改参数 ==================== + TARGET_STOCK_CODE = "300418" # 股票代码 + # ===================================================== + + print("股票全历史数据获取工具") + print("说明:修改代码中的 TARGET_STOCK_CODE 来获取不同股票的全部历史数据") + print(f"当前设置: 股票代码={TARGET_STOCK_CODE}") + print() + + # 运行主程序 + main_all_history(stock_code=TARGET_STOCK_CODE) + + print(f"\n💡 提示:要获取其他股票的全历史数据,请修改代码中的 TARGET_STOCK_CODE 变量") \ No newline at end of file diff --git a/examples/prediction_akshare_2024-2025.py b/examples/prediction_akshare_2024-2025.py new file mode 100644 index 0000000..6b83eb2 --- /dev/null +++ b/examples/prediction_akshare_2024-2025.py @@ -0,0 +1,545 @@ +import pandas as pd +import matplotlib.pyplot as plt +import numpy as np +import sys +import os +from datetime import datetime, timedelta +import warnings + +warnings.filterwarnings('ignore') + +# 添加项目路径以便导入自定义模块 +sys.path.append("../") +from model import Kronos, KronosTokenizer, KronosPredictor + +# 设置中文字体 +plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签 +plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号 + + +def ensure_output_directory(output_dir): + """确保输出目录存在,如果不存在则创建""" + if not os.path.exists(output_dir): + os.makedirs(output_dir) + print(f"✅ 创建输出目录: {output_dir}") + return output_dir + + +def prepare_stock_data(csv_file_path, stock_code): + """ + 准备股票数据,转换为Kronos模型需要的格式 + + 参数: + csv_file_path: CSV文件路径 + stock_code: 股票代码,用于显示信息 + + 返回: + df: 处理后的DataFrame + """ + print(f"正在加载和预处理股票 {stock_code} 数据...") + + # 读取CSV文件 + df = pd.read_csv(csv_file_path, encoding='utf-8-sig') + + # 检查数据列名并重命名为标准格式 + column_mapping = { + '日期': 'timestamps', + '开盘价': 'open', + '最高价': 'high', + '最低价': 'low', + '收盘价': 'close', + '成交量': 'volume', + '成交额': 'amount' + } + + # 只重命名存在的列 + actual_mapping = {k: v for k, v in column_mapping.items() if k in df.columns} + df = df.rename(columns=actual_mapping) + + # 确保时间戳列存在并转换为datetime格式 + if 'timestamps' not in df.columns: + # 如果数据有日期索引,重置索引 + if df.index.name == '日期': + df = df.reset_index() + df = df.rename(columns={'日期': 'timestamps'}) + + df['timestamps'] = pd.to_datetime(df['timestamps']) + + # 按时间排序 + df = df.sort_values('timestamps').reset_index(drop=True) + + print(f"✅ 数据加载完成,共 {len(df)} 条记录") + print(f"时间范围: {df['timestamps'].min()} 到 {df['timestamps'].max()}") + print(f"数据列: {df.columns.tolist()}") + + return df + + +def calculate_prediction_parameters(df, target_days=100): + """ + 根据目标预测天数计算合适的参数 + + 参数: + df: 股票数据DataFrame + target_days: 目标预测天数(自然日) + + 返回: + lookback: 回看期数 + pred_len: 预测期数 + """ + # 计算平均交易日数量(考虑节假日) + total_days = (df['timestamps'].max() - df['timestamps'].min()).days + trading_days = len(df) + trading_ratio = trading_days / total_days if total_days > 0 else 0.7 # 交易日比例 + + # 计算目标预测的交易日数量 + pred_trading_days = int(target_days * trading_ratio) + + # 设置回看期数为预测期数的2-3倍,但不超过数据总量的70% + max_lookback = int(len(df) * 0.7) + lookback = min(pred_trading_days * 2, max_lookback, len(df) - pred_trading_days) + pred_len = min(pred_trading_days, len(df) - lookback) + + print(f"📊 参数计算:") + print(f" 目标预测天数: {target_days} 天(自然日)") + print(f" 预计交易日数量: {pred_trading_days} 天") + print(f" 回看期数 (lookback): {lookback}") + print(f" 预测期数 (pred_len): {pred_len}") + + return lookback, pred_len + + +def generate_future_dates_with_holidays(last_date, pred_len): + """ + 生成未来的交易日日期,考虑中国节假日 + + 参数: + last_date: 最后一个历史数据的日期 + pred_len: 预测期数 + + 返回: + future_dates: 未来的交易日日期列表 + """ + # 中国主要节假日(需要根据实际情况调整) + holidays_2025 = [ + # 2025年国庆节假期(通常为10月1日-10月8日) + datetime(2025, 10, 1), datetime(2025, 10, 2), datetime(2025, 10, 3), + datetime(2025, 10, 4), datetime(2025, 10, 5), datetime(2025, 10, 6), + datetime(2025, 10, 7), datetime(2025, 10, 8), # 添加10月8日 + # 周末调休等可以根据需要添加 + ] + + future_dates = [] + current_date = last_date + timedelta(days=1) + + while len(future_dates) < pred_len: + # 如果是工作日(周一到周五)且不是节假日 + if current_date.weekday() < 5 and current_date not in holidays_2025: + future_dates.append(current_date) + current_date += timedelta(days=1) + + print(f"📅 生成的未来交易日: 共 {len(future_dates)} 天") + print(f" 起始日期: {future_dates[0].strftime('%Y-%m-%d')}") + print(f" 结束日期: {future_dates[-1].strftime('%Y-%m-%d')}") + + # 显示节假日信息 + holiday_count = sum(1 for date in holidays_2025 if date > last_date) + print(f" 包含节假日: {holiday_count} 天") + + return future_dates[:pred_len] + + +def plot_prediction_with_details(kline_df, pred_df, future_dates, stock_code="002354", stock_name="股票", pred_len=100, + output_dir="."): + """ + 绘制详细的预测结果图表 - 优化版,图表更大更清晰 + + 参数: + kline_df: 历史K线数据 + pred_df: 预测数据 + future_dates: 未来日期列表 + stock_code: 股票代码 + stock_name: 股票名称 + pred_len: 预测期数 + output_dir: 输出目录 + """ + # 确保输出目录存在 + ensure_output_directory(output_dir) + + # 确保数据长度一致 + min_len = min(len(pred_df), len(future_dates)) + pred_df = pred_df.iloc[:min_len] + future_dates = future_dates[:min_len] + + # 设置预测数据的索引为未来日期 + pred_df.index = future_dates + + # 准备价格数据 + sr_close = kline_df.set_index('timestamps')['close'] + sr_pred_close = pred_df['close'] + sr_close.name = '历史数据' + sr_pred_close.name = "预测数据" + + # 准备成交量数据 + sr_volume = kline_df.set_index('timestamps')['volume'] + sr_pred_volume = pred_df['volume'] + sr_volume.name = '历史数据' + sr_pred_volume.name = "预测数据" + + # 合并数据 + close_df = pd.concat([sr_close, sr_pred_close], axis=1) + volume_df = pd.concat([sr_volume, sr_pred_volume], axis=1) + + # 创建更大的图表 + fig = plt.figure(figsize=(18, 14)) + + # 使用GridSpec创建更灵活的布局 + gs = plt.GridSpec(3, 1, figure=fig, height_ratios=[3, 1, 1]) + + ax1 = fig.add_subplot(gs[0]) # 价格图表 + ax2 = fig.add_subplot(gs[1]) # 成交量图表 + ax3 = fig.add_subplot(gs[2]) # 价格变动图表 + + # 1. 价格图表 - 更大更清晰 + # 只显示最近200个交易日的历史数据,避免图表过于拥挤 + recent_history = close_df['历史数据'].iloc[-min(200, len(close_df['历史数据'])):] + ax1.plot(recent_history.index, recent_history.values, label='历史价格', color='#1f77b4', linewidth=2.5, alpha=0.9) + ax1.plot(close_df['预测数据'].index, close_df['预测数据'].values, label='预测价格', + color='#ff7f0e', linewidth=2.5, linestyle='-', marker='o', markersize=3) + + # 添加预测起始点的标记 + prediction_start_date = close_df['预测数据'].index[0] if len(close_df['预测数据']) > 0 else close_df.index[-1] + prediction_start_price = close_df['历史数据'].iloc[-1] + ax1.axvline(x=prediction_start_date, color='red', linestyle='--', alpha=0.7, linewidth=1.5) + ax1.annotate('预测起点', xy=(prediction_start_date, prediction_start_price), + xytext=(10, 10), textcoords='offset points', + bbox=dict(boxstyle='round,pad=0.3', facecolor='yellow', alpha=0.7), + arrowprops=dict(arrowstyle='->', connectionstyle='arc3,rad=0')) + + ax1.set_ylabel('收盘价 (元)', fontsize=14, fontweight='bold') + ax1.legend(loc='upper left', fontsize=12) + ax1.grid(True, alpha=0.3) + ax1.set_title(f'{stock_name}({stock_code}) 股票价格预测 - 未来{pred_len}个交易日', + fontsize=16, fontweight='bold', pad=20) + + # 设置x轴日期格式 + ax1.xaxis.set_major_formatter(plt.matplotlib.dates.DateFormatter('%Y-%m-%d')) + plt.setp(ax1.xaxis.get_majorticklabels(), rotation=45) + + # 设置y轴格式 + ax1.yaxis.set_major_formatter(plt.FuncFormatter(lambda x, p: f'{x:.2f}')) + + # 2. 成交量图表 - 优化显示 + # 只显示预测期的成交量 + pred_volumes = volume_df['预测数据'].dropna() + if len(pred_volumes) > 0: + ax2.bar(pred_volumes.index, pred_volumes.values, + alpha=0.7, color='#ff7f0e', label='预测成交量', width=0.8) + + ax2.set_ylabel('成交量 (手)', fontsize=14, fontweight='bold') + ax2.legend(loc='upper left', fontsize=12) + ax2.grid(True, alpha=0.3) + + # 设置x轴标签 + if len(pred_volumes) > 0: + ax2.xaxis.set_major_formatter(plt.matplotlib.dates.DateFormatter('%m-%d')) + plt.setp(ax2.xaxis.get_majorticklabels(), rotation=45) + + # 3. 价格变动图表 - 优化显示 + if len(close_df['预测数据']) > 0: + price_change = close_df['预测数据'] - close_df['历史数据'].iloc[-1] + colors = ['green' if x >= 0 else 'red' for x in price_change] + + # 每5个交易日显示一个标签,避免过于拥挤 + bars = ax3.bar(range(len(price_change)), price_change, alpha=0.8, color=colors) + + # 在关键点添加数值标签 + for i, bar in enumerate(bars): + height = bar.get_height() + if i % 10 == 0 or i == len(bars) - 1 or abs(height) > price_change.std(): # 每10天或最后一天或显著波动 + ax3.text(bar.get_x() + bar.get_width() / 2., height, + f'{height:+.2f}', ha='center', va='bottom' if height >= 0 else 'top', + fontsize=8, fontweight='bold') + + ax3.axhline(y=0, color='black', linestyle='-', alpha=0.5, linewidth=1) + + ax3.set_ylabel('价格变动 (元)', fontsize=14, fontweight='bold') + ax3.set_xlabel('交易日', fontsize=14, fontweight='bold') + ax3.grid(True, alpha=0.3) + + # 设置x轴标签 + if len(price_change) > 0: + # 每10个交易日显示一个标签 + xticks_positions = list(range(0, len(price_change), max(1, len(price_change) // 10))) + if len(price_change) - 1 not in xticks_positions: + xticks_positions.append(len(price_change) - 1) + ax3.set_xticks(xticks_positions) + ax3.set_xticklabels([f'D{i + 1}' for i in xticks_positions]) + + # 添加详细的统计信息框 + if len(close_df['预测数据']) > 0 and not np.isnan(close_df['历史数据'].iloc[-1]): + pred_stats = { + '股票代码': stock_code, + '股票名称': stock_name, + '当前价格': f"{close_df['历史数据'].iloc[-1]:.2f} 元", + '预测结束价格': f"{close_df['预测数据'].iloc[-1]:.2f} 元", + '预测涨跌幅': f"{(close_df['预测数据'].iloc[-1] / close_df['历史数据'].iloc[-1] - 1) * 100:+.2f}%", + '预测期间最高价': f"{close_df['预测数据'].max():.2f} 元", + '预测期间最低价': f"{close_df['预测数据'].min():.2f} 元", + '预测波动率': f"{close_df['预测数据'].std():.2f} 元", + '预测起始日期': f"{close_df['预测数据'].index[0].strftime('%Y-%m-%d')}", + '预测结束日期': f"{close_df['预测数据'].index[-1].strftime('%Y-%m-%d')}", + '预测交易日数': f"{len(close_df['预测数据'])} 天" + } + + stats_text = "\n".join([f"{k}: {v}" for k, v in pred_stats.items()]) + fig.text(0.02, 0.02, stats_text, fontsize=10, + bbox=dict(boxstyle="round,pad=0.5", facecolor="lightblue", alpha=0.8), + verticalalignment='bottom') + + plt.tight_layout() + + # 保存高分辨率图片到指定目录 + chart_filename = os.path.join(output_dir, f'{stock_code}_prediction_chart.png') + plt.savefig(chart_filename, dpi=300, bbox_inches='tight', facecolor='white') + print(f"📊 预测图表已保存: {chart_filename}") + + plt.show() + + return close_df, volume_df + + +def generate_prediction_report(close_df, volume_df, pred_df, future_dates, stock_code="002354", stock_name="股票", + output_dir="."): + """ + 生成预测报告 + """ + # 确保输出目录存在 + ensure_output_directory(output_dir) + + print(f"\n{'=' * 70}") + print(f"📊 {stock_name}({stock_code}) 股票预测报告") + print(f"{'=' * 70}") + + if len(close_df['预测数据']) == 0 or np.isnan(close_df['历史数据'].iloc[-1]): + print("❌ 没有有效的预测数据可生成报告") + return + + # 确保所有数组长度一致 + min_len = min(len(close_df['预测数据']), len(volume_df['预测数据']), len(future_dates)) + + # 基本统计 + historical_close = close_df['历史数据'].iloc[-1] + predicted_close = close_df['预测数据'].iloc[-1] + price_change_pct = (predicted_close / historical_close - 1) * 100 + + print(f"🔮 预测概览:") + print(f" 当前价格: {historical_close:.2f} 元") + print(f" 预测结束价格: {predicted_close:.2f} 元") + print(f" 预测涨跌幅: {price_change_pct:+.2f}%") + print(f" 预测期间: {min_len} 个交易日") + print( + f" 预测时间范围: {future_dates[0].strftime('%Y-%m-%d')} 到 {future_dates[min_len - 1].strftime('%Y-%m-%d')}") + + print(f"\n📈 价格预测统计:") + print(f" 预测最高价: {close_df['预测数据'].max():.2f} 元") + print(f" 预测最低价: {close_df['预测数据'].min():.2f} 元") + print(f" 预测平均价: {close_df['预测数据'].mean():.2f} 元") + print(f" 价格波动率: {close_df['预测数据'].std():.2f} 元") + + print(f"\n📊 成交量预测统计:") + print(f" 预测平均成交量: {volume_df['预测数据'].mean():,.0f} 手") + print(f" 预测最大成交量: {volume_df['预测数据'].max():,.0f} 手") + print(f" 预测最小成交量: {volume_df['预测数据'].min():,.0f} 手") + + # 保存详细预测数据到指定目录 - 确保所有数组长度一致 + prediction_details = pd.DataFrame({ + '日期': future_dates[:min_len], + '预测收盘价': close_df['预测数据'].values[:min_len], + '预测成交量': volume_df['预测数据'].values[:min_len], + '价格变动(元)': (close_df['预测数据'].values[:min_len] - historical_close), + '价格变动(%)': ((close_df['预测数据'].values[:min_len] / historical_close - 1) * 100) + }) + + prediction_file = os.path.join(output_dir, f'{stock_code}_detailed_predictions.csv') + prediction_details.to_csv(prediction_file, index=False, encoding='utf-8-sig') + print(f"\n💾 详细预测数据已保存: {prediction_file}") + + +def main(stock_code="002354", stock_name="天娱数科", data_dir="./data", pred_days=100, output_dir="./output"): + """ + 主函数:执行股票价格预测 + + 参数: + stock_code: 股票代码 + stock_name: 股票名称 + data_dir: 数据文件目录 + pred_days: 预测天数(自然日) + output_dir: 输出文件目录 + """ + # 构建数据文件路径 + csv_file_path = os.path.join(data_dir, f"{stock_code}_stock_data.csv") + + print(f"🎯 开始 {stock_name}({stock_code}) 股票价格预测") + print("=" * 70) + print(f"数据文件: {csv_file_path}") + print(f"预测天数: {pred_days} 天(自然日)") + print(f"输出目录: {output_dir}") + + # 检查数据文件是否存在 + if not os.path.exists(csv_file_path): + print(f"❌ 数据文件不存在: {csv_file_path}") + print("请先运行数据获取脚本生成股票数据文件") + return + + # 确保输出目录存在 + ensure_output_directory(output_dir) + + try: + # 1. 加载模型和分词器 + print("\n步骤1: 加载Kronos模型和分词器...") + tokenizer = KronosTokenizer.from_pretrained("NeoQuasar/Kronos-Tokenizer-base") + model = Kronos.from_pretrained("NeoQuasar/Kronos-base") + print("✅ 模型加载完成") + + # 2. 实例化预测器 + print("步骤2: 初始化预测器...") + predictor = KronosPredictor(model, tokenizer, device="cuda:0", max_context=512) + print("✅ 预测器初始化完成") + + # 3. 准备数据 + print("步骤3: 准备股票数据...") + df = prepare_stock_data(csv_file_path, stock_code) + + # 4. 计算预测参数 + print("步骤4: 计算预测参数...") + lookback, pred_len = calculate_prediction_parameters(df, target_days=pred_days) + + if pred_len <= 0: + print("❌ 数据量不足,无法进行预测") + return + + print(f"✅ 最终参数 - 回看期: {lookback}, 预测期: {pred_len}") + + # 5. 准备输入数据 + print("步骤5: 准备输入数据...") + # 使用最新的数据作为输入 + x_df = df.loc[-lookback:, ['open', 'high', 'low', 'close', 'volume', 'amount']].reset_index(drop=True) + x_timestamp = df.loc[-lookback:, 'timestamps'].reset_index(drop=True) + + # 生成未来日期(考虑节假日) + last_historical_date = df['timestamps'].iloc[-1] + future_dates = generate_future_dates_with_holidays(last_historical_date, pred_len) + + print(f"输入数据形状: {x_df.shape}") + print(f"历史数据时间范围: {x_timestamp.iloc[0]} 到 {x_timestamp.iloc[-1]}") + print(f"预测时间范围: {future_dates[0]} 到 {future_dates[-1]}") + + # 6. 执行预测 + print("步骤6: 执行价格预测...") + pred_df = predictor.predict( + df=x_df, + x_timestamp=x_timestamp, + y_timestamp=pd.Series(future_dates), # 使用未来日期作为预测时间戳 + pred_len=pred_len, + T=1.0, + top_p=0.9, + sample_count=1, + verbose=True + ) + + print("✅ 预测完成") + + # 7. 显示预测结果 + print("\n步骤7: 显示预测结果...") + print("预测数据前5行:") + # 确保预测数据长度与未来日期一致 + min_len = min(len(pred_df), len(future_dates)) + pred_df = pred_df.iloc[:min_len] + pred_df.index = future_dates[:min_len] + print(pred_df.head()) + + # 8. 可视化结果 + print("步骤8: 生成可视化图表...") + # 使用最后一部分历史数据和预测数据 + kline_df = df.loc[-lookback:].reset_index(drop=True) + close_df, volume_df = plot_prediction_with_details(kline_df, pred_df, future_dates, stock_code, stock_name, + pred_len, output_dir) + + # 9. 生成预测报告 + print("步骤9: 生成预测报告...") + generate_prediction_report(close_df, volume_df, pred_df, future_dates, stock_code, stock_name, output_dir) + + print(f"\n🎉 {stock_name}({stock_code}) 股票预测完成!") + print("生成的文件:") + print(f" 📊 {os.path.join(output_dir, stock_code + '_prediction_chart.png')} - 预测图表") + print(f" 📋 {os.path.join(output_dir, stock_code + '_detailed_predictions.csv')} - 详细预测数据") + + # 显示预测总结 + if len(close_df['预测数据']) > 0 and not np.isnan(close_df['历史数据'].iloc[-1]): + print(f"\n📈 预测总结:") + historical_price = close_df['历史数据'].iloc[-1] + predicted_price = close_df['预测数据'].iloc[-1] + change_pct = (predicted_price / historical_price - 1) * 100 + + print(f" 当前价格: {historical_price:.2f} 元") + print(f" 预测价格: {predicted_price:.2f} 元") + print(f" 预期涨跌: {change_pct:+.2f}%") + print( + f" 预测时间: {future_dates[0].strftime('%Y-%m-%d')} 到 {future_dates[min_len - 1].strftime('%Y-%m-%d')}") + + if change_pct > 10: + print(f" 🚀 模型预测未来{pred_len}个交易日大幅看涨 (+{change_pct:.1f}%)") + elif change_pct > 5: + print(f" 📈 模型预测未来{pred_len}个交易日看涨 (+{change_pct:.1f}%)") + elif change_pct > 0: + print(f" ↗️ 模型预测未来{pred_len}个交易日微涨 (+{change_pct:.1f}%)") + elif change_pct > -5: + print(f" ↘️ 模型预测未来{pred_len}个交易日微跌 ({change_pct:.1f}%)") + elif change_pct > -10: + print(f" 📉 模型预测未来{pred_len}个交易日看跌 ({change_pct:.1f}%)") + else: + print(f" 🔻 模型预测未来{pred_len}个交易日大幅看跌 ({change_pct:.1f}%)") + + except Exception as e: + print(f"❌ 预测过程中出现错误: {e}") + import traceback + traceback.print_exc() + + +# 使用方法说明 +if __name__ == "__main__": + """ + 股票预测工具 - 支持多股票预测 + + 使用方法: + 修改下面的 STOCK_CONFIG 来预测不同的股票 + """ + + # ==================== 在这里修改股票配置 ==================== + STOCK_CONFIG = { + "stock_code": "300418", # 股票代码 + "stock_name": "昆仑万维", # 股票名称 + "data_dir": "./data", # 数据文件目录 + "pred_days": 100, # 预测100个自然日 + "output_dir": r"D:\lianghuajiaoyi\Kronos\examples\yuce" # 输出文件目录 + } + + # 其他股票配置示例: + # STOCK_CONFIG = {"stock_code": "000001", "stock_name": "平安银行", "data_dir": "./data", "pred_days": 100, "output_dir": r"D:\lianghuajiaoyi\Kronos\examples\yuce"} + # STOCK_CONFIG = {"stock_code": "600036", "stock_name": "招商银行", "data_dir": "./data", "pred_days": 100, "output_dir": r"D:\lianghuajiaoyi\Kronos\examples\yuce"} + # STOCK_CONFIG = {"stock_code": "300750", "stock_name": "宁德时代", "data_dir": "./data", "pred_days": 100, "output_dir": r"D:\lianghuajiaoyi\Kronos\examples\yuce"} + # ========================================================= + + print("🤖 智能股票预测工具") + print("=" * 70) + print(f"当前预测股票: {STOCK_CONFIG['stock_name']}({STOCK_CONFIG['stock_code']})") + print(f"数据目录: {STOCK_CONFIG['data_dir']}") + print(f"预测天数: {STOCK_CONFIG['pred_days']} 天(自然日)") + print(f"输出目录: {STOCK_CONFIG['output_dir']}") + print() + + # 运行主程序 + main(**STOCK_CONFIG) + + print(f"\n💡 提示:要预测其他股票,请修改代码中的 STOCK_CONFIG 变量") \ No newline at end of file diff --git a/examples/prediction_new.py b/examples/prediction_new.py new file mode 100644 index 0000000..3646d98 --- /dev/null +++ b/examples/prediction_new.py @@ -0,0 +1,1333 @@ +import pandas as pd +import matplotlib.pyplot as plt +import numpy as np +import sys +import os +from datetime import datetime, timedelta +import warnings +import requests +import json +import time +import random +import akshare as ak +from typing import Dict, List, Tuple, Optional + +warnings.filterwarnings('ignore') + +# 添加项目路径以便导入自定义模块 +sys.path.append("../") +try: + from model import Kronos, KronosTokenizer, KronosPredictor +except ImportError: + print("⚠️ 无法导入Kronos模型,预测功能将不可用") + +# 设置中文字体 +plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签 +plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号 + + +# ==================== 基础数据获取函数 ==================== +def ensure_output_directory(output_dir): + """确保输出目录存在,如果不存在则创建""" + if not os.path.exists(output_dir): + os.makedirs(output_dir) + print(f"✅ 创建输出目录: {output_dir}") + return output_dir + + +def fetch_real_stock_data(stock_code, period="daily", adjust="qfq"): + """ + 使用AKShare获取真实股票数据 + """ + try: + print(f"📡 正在通过AKShare获取 {stock_code} 的真实股票数据...") + + # 获取股票数据 + df = ak.stock_zh_a_hist(symbol=stock_code, period=period, adjust=adjust) + + if df is None or df.empty: + print(f"❌ 未获取到 {stock_code} 的数据") + return None + + # 重命名列以统一格式 + column_mapping = { + '日期': 'timestamps', + '开盘': 'open', + '收盘': 'close', + '最高': 'high', + '最低': 'low', + '成交量': 'volume', + '成交额': 'amount', + '振幅': 'amplitude', + '涨跌幅': 'pct_chg', + '涨跌额': 'change_amount', + '换手率': 'turnover' + } + + # 只映射存在的列 + actual_mapping = {k: v for k, v in column_mapping.items() if k in df.columns} + df = df.rename(columns=actual_mapping) + + # 确保时间戳格式正确 + df['timestamps'] = pd.to_datetime(df['timestamps']) + df = df.sort_values('timestamps').reset_index(drop=True) + + # 添加股票代码列 + df['stock_code'] = stock_code + + print(f"✅ 成功获取 {len(df)} 条真实数据") + print(f"📈 最新收盘价: {df['close'].iloc[-1]:.2f}元, 涨跌幅: {df['pct_chg'].iloc[-1]:.2f}%") + print(f"📅 时间范围: {df['timestamps'].min()} 到 {df['timestamps'].max()}") + + return df + + except Exception as e: + print(f"❌ AKShare数据获取失败: {e}") + return None + + +def get_stock_data_with_retry_all_history(stock_code="600580", retry_count=2): + """ + 优化的数据获取函数 - 优先使用真实API数据 + """ + print(f"🔄 尝试获取股票 {stock_code} 的真实历史数据...") + + # 优先使用AKShare获取真实数据 + df = fetch_real_stock_data(stock_code, "daily", "qfq") + + if df is not None: + return df + else: + print("⚠️ 真实数据获取失败,使用基于真实价格的模拟数据...") + return create_realistic_fallback_data(stock_code) + + +def create_realistic_fallback_data(stock_code="600580"): + """ + 基于真实价格的备用数据生成函数 + """ + # 基于真实市场价格的参考数据 + real_stock_references = { + '600580': {'name': '卧龙电驱', 'current_price': 15.20, 'range': (12.0, 20.0)}, + '300207': {'name': '欣旺达', 'current_price': 33.79, 'range': (28.0, 38.0)}, + '300418': {'name': '昆仑万维', 'current_price': 48.59, 'range': (40.0, 55.0)}, + '002354': {'name': '天娱数科', 'current_price': 15.20, 'range': (12.0, 20.0)}, + '000001': {'name': '平安银行', 'current_price': 12.50, 'range': (10.0, 16.0)}, + '600036': {'name': '招商银行', 'current_price': 35.80, 'range': (30.0, 42.0)}, + } + + stock_info = real_stock_references.get(stock_code, { + 'name': '未知股票', + 'current_price': 20.0, + 'range': (15.0, 25.0) + }) + + # 生成最近1年的交易日数据 + end_date = datetime.now() + start_date = end_date - timedelta(days=365) + dates = pd.bdate_range(start=start_date, end=end_date, freq='B') + + # 生成基于真实价格的价格序列 + np.random.seed(42) + n_points = len(dates) + + # 从当前价格反向生成历史价格 + current_price = stock_info['current_price'] + min_price, max_price = stock_info['range'] + + # 反向生成价格序列 + prices = [current_price] + for i in range(1, n_points): + volatility = 0.02 + historical_return = np.random.normal(-0.0002, volatility) + + prev_price = prices[0] * (1 + historical_return) + prev_price = max(min_price * 0.9, min(max_price * 1.1, prev_price)) + prices.insert(0, prev_price) + + # 生成OHLC数据 + stock_data = [] + for i, date in enumerate(dates): + close_price = prices[i] + + daily_volatility = abs(np.random.normal(0, 0.015)) + open_price = close_price * (1 + np.random.normal(0, 0.005)) + high_price = max(open_price, close_price) * (1 + daily_volatility) + low_price = min(open_price, close_price) * (1 - daily_volatility) + + high_price = max(open_price, close_price, low_price, high_price) + low_price = min(open_price, close_price, high_price, low_price) + + volume = int(abs(np.random.normal(1500000, 400000))) + amount = volume * close_price + + if i > 0: + pct_chg = ((close_price - prices[i - 1]) / prices[i - 1]) * 100 + change_amount = close_price - prices[i - 1] + else: + pct_chg = 0 + change_amount = 0 + + stock_data.append({ + 'timestamps': date, + 'stock_code': stock_code, + 'open': round(open_price, 2), + 'close': round(close_price, 2), + 'high': round(high_price, 2), + 'low': round(low_price, 2), + 'volume': volume, + 'amount': round(amount, 2), + 'amplitude': round(((high_price - low_price) / open_price) * 100, 2), + 'pct_chg': round(pct_chg, 2), + 'change_amount': round(change_amount, 2), + 'turnover': round(np.random.uniform(3.0, 8.0), 2) + }) + + df = pd.DataFrame(stock_data) + print(f"✅ 已生成基于真实价格的备用数据 {len(df)} 条") + return df + + +def save_all_history_stock_data(df, stock_code, save_dir): + """ + 保存股票数据到指定目录 + """ + if df is not None and not df.empty: + os.makedirs(save_dir, exist_ok=True) + csv_file = os.path.join(save_dir, f"{stock_code}_stock_data.csv") + df_reset = df.reset_index() + df_reset.to_csv(csv_file, encoding='utf-8-sig', index=False) + print(f"📁 股票数据已保存: {csv_file}") + return True + return False + + +def get_stock_data(stock_code, data_dir): + """ + 获取股票数据,如果数据文件不存在则从API获取真实数据 + """ + csv_file_path = os.path.join(data_dir, f"{stock_code}_stock_data.csv") + + if os.path.exists(csv_file_path): + print(f"📁 使用现有数据文件: {csv_file_path}") + return True, csv_file_path + else: + print(f"📡 数据文件不存在,从API获取真实数据...") + df = get_stock_data_with_retry_all_history(stock_code) + + if df is not None and not df.empty: + save_all_history_stock_data(df, stock_code, data_dir) + return True, csv_file_path + else: + print(f"❌ 无法获取股票数据") + return False, None + + +def prepare_stock_data(csv_file_path, stock_code, history_years=1): + """ + 准备股票数据,转换为Kronos模型需要的格式 + """ + print(f"正在加载和预处理股票 {stock_code} 数据...") + + # 读取CSV文件 + df = pd.read_csv(csv_file_path, encoding='utf-8-sig') + + # 标准化列名 + column_mapping = { + '日期': 'timestamps', + '开盘价': 'open', + '最高价': 'high', + '最低价': 'low', + '收盘价': 'close', + '成交量': 'volume', + '成交额': 'amount', + '开盘': 'open', + '收盘': 'close', + '最高': 'high', + '最低': 'low' + } + + actual_mapping = {k: v for k, v in column_mapping.items() if k in df.columns} + df = df.rename(columns=actual_mapping) + + # 确保时间戳列存在并转换为datetime格式 + if 'timestamps' not in df.columns: + if df.index.name == '日期': + df = df.reset_index() + df = df.rename(columns={'日期': 'timestamps'}) + + df['timestamps'] = pd.to_datetime(df['timestamps']) + df = df.sort_values('timestamps').reset_index(drop=True) + + # 根据历史年限筛选数据 + if history_years > 0: + cutoff_date = datetime.now() - timedelta(days=history_years * 365) + original_count = len(df) + df = df[df['timestamps'] >= cutoff_date] + print(f"📅 使用最近 {history_years} 年数据: {len(df)} 条记录 (从 {original_count} 条中筛选)") + + # 数据验证 + print(f"🔍 数据验证 - 最近5个交易日收盘价:") + recent_prices = df[['timestamps', 'close']].tail() + for _, row in recent_prices.iterrows(): + print(f" {row['timestamps'].strftime('%Y-%m-%d')}: {row['close']:.2f}元") + + current_price = df['close'].iloc[-1] + print(f"✅ 数据加载完成,共 {len(df)} 条记录") + print(f"时间范围: {df['timestamps'].min()} 到 {df['timestamps'].max()}") + print(f"价格范围: {df['close'].min():.2f} - {df['close'].max():.2f}") + print(f"当前价格: {current_price:.2f}元") + + return df + + +def calculate_prediction_parameters(df, target_days=60): + """ + 根据目标预测天数计算合适的参数 + """ + # 计算平均交易日数量 + total_days = (df['timestamps'].max() - df['timestamps'].min()).days + trading_days = len(df) + trading_ratio = trading_days / total_days if total_days > 0 else 0.7 + + # 计算目标预测的交易日数量 + pred_trading_days = int(target_days * trading_ratio) + + # 设置回看期数 + max_lookback = int(len(df) * 0.7) + lookback = min(pred_trading_days * 3, max_lookback, len(df) - pred_trading_days) + pred_len = min(pred_trading_days, len(df) - lookback) + + # 确保参数在合理范围内 + lookback = max(100, min(lookback, 400)) + pred_len = max(20, min(pred_len, 120)) + + print(f"📊 参数计算:") + print(f" 目标预测天数: {target_days} 天(自然日)") + print(f" 预计交易日数量: {pred_trading_days} 天") + print(f" 回看期数 (lookback): {lookback}") + print(f" 预测期数 (pred_len): {pred_len}") + + return lookback, pred_len + + +def generate_future_dates(last_date, pred_len): + """ + 生成未来的交易日日期 + """ + future_dates = [] + current_date = last_date + timedelta(days=1) + + while len(future_dates) < pred_len: + if current_date.weekday() < 5: + future_dates.append(current_date) + current_date += timedelta(days=1) + + print(f"📅 生成的未来交易日: 共 {len(future_dates)} 天") + print(f" 起始日期: {future_dates[0].strftime('%Y-%m-%d')}") + print(f" 结束日期: {future_dates[-1].strftime('%Y-%m-%d')}") + + return future_dates[:pred_len] + + +def calculate_optimal_interval(min_val, max_val): + """ + 计算最优的Y轴刻度间隔 + """ + range_val = max_val - min_val + if range_val <= 0: + return 1.0 + + if range_val < 1: + interval = 0.1 + elif range_val < 5: + interval = 0.5 + elif range_val < 10: + interval = 1.0 + elif range_val < 20: + interval = 2.0 + elif range_val < 50: + interval = 5.0 + elif range_val < 100: + interval = 10.0 + elif range_val < 200: + interval = 20.0 + elif range_val < 500: + interval = 50.0 + else: + interval = 100.0 + + return interval + + +def get_stock_price_reference(stock_code, current_price): + """ + 根据当前价格智能计算参考价格范围 + """ + price_ranges = { + '600580': (current_price * 0.75, current_price * 1.25), + '300207': (current_price * 0.75, current_price * 1.25), + '300418': (current_price * 0.75, current_price * 1.25), + '002354': (current_price * 0.75, current_price * 1.25), + '000001': (current_price * 0.75, current_price * 1.25), + '600036': (current_price * 0.75, current_price * 1.25), + } + + if stock_code in price_ranges: + min_price, max_price = price_ranges[stock_code] + min_price = max(1.0, min_price) + return {'min': min_price, 'max': max_price} + else: + return {'min': max(1.0, current_price * 0.7), 'max': current_price * 1.3} + + +# ==================== 增强版市场因素分析器 ==================== +class EnhancedMarketFactorAnalyzer: + """增强版市场因素分析器 - 整合更多维度的市场因素""" + + def __init__(self): + self.market_data = {} + self.sector_data = {} + self.macro_factors = {} + self.policy_factors = {} + + def analyze_market_trend(self, index_codes=["000001", "399001"]): + """ + 分析大盘趋势 - 多指数综合分析 + """ + try: + print(f"📊 综合分析大盘趋势...") + + market_analysis = {} + + for index_code in index_codes: + index_name = "上证指数" if index_code == "000001" else "深证成指" + print(f" 分析{index_name}({index_code})...") + + # 获取指数数据 + index_df = ak.stock_zh_index_hist(symbol=index_code, period="daily") + + if index_df is None or index_df.empty: + print(f" ❌ 无法获取{index_name}数据") + continue + + # 重命名列 + index_df = index_df.rename(columns={ + '日期': 'date', '收盘': 'close', '开盘': 'open', + '最高': 'high', '最低': 'low', '成交量': 'volume' + }) + index_df['date'] = pd.to_datetime(index_df['date']) + index_df = index_df.sort_values('date').reset_index(drop=True) + + # 计算技术指标 + index_df['ma5'] = index_df['close'].rolling(5).mean() + index_df['ma20'] = index_df['close'].rolling(20).mean() + index_df['ma60'] = index_df['close'].rolling(60).mean() + index_df['vol_ma5'] = index_df['volume'].rolling(5).mean() + + # 技术分析 + current_data = index_df.iloc[-1] + prev_data = index_df.iloc[-2] + + # 均线多头排列判断 + ma_condition = (current_data['ma5'] > current_data['ma20'] > current_data['ma60']) + + # 价格站在20日均线以上 + price_above_ma20 = current_data['close'] > current_data['ma20'] + + # 成交量配合 + volume_condition = current_data['volume'] > current_data['vol_ma5'] * 0.8 + + # 趋势强度 + trend_strength = self._calculate_trend_strength(index_df) + + is_main_uptrend = ma_condition and price_above_ma20 and trend_strength > 0.6 + + market_analysis[index_name] = { + 'is_main_uptrend': is_main_uptrend, + 'trend_strength': trend_strength, + 'current_close': current_data['close'], + 'price_change_pct': ((current_data['close'] - prev_data['close']) / prev_data['close']) * 100, + 'market_status': '主升浪' if is_main_uptrend else '震荡调整' + } + + # 综合判断 + if market_analysis: + avg_trend_strength = np.mean([data['trend_strength'] for data in market_analysis.values()]) + uptrend_count = sum(1 for data in market_analysis.values() if data['is_main_uptrend']) + overall_uptrend = uptrend_count >= len(market_analysis) * 0.5 + + final_analysis = { + 'overall_is_main_uptrend': overall_uptrend, + 'overall_trend_strength': avg_trend_strength, + 'detailed_analysis': market_analysis, + 'market_status': '主升浪' if overall_uptrend else '震荡调整' + } + + print(f"✅ 大盘分析完成: {final_analysis['market_status']}, 综合趋势强度: {avg_trend_strength:.2f}") + return final_analysis + + return self._get_default_market_analysis() + + except Exception as e: + print(f"❌ 大盘分析错误: {e}") + return self._get_default_market_analysis() + + def analyze_sector_resonance(self, stock_code): + """ + 分析板块共振效应 - 增强版行业分析 + """ + try: + print(f"🔄 分析板块共振效应...") + + # 获取股票所属行业和概念 + industry = "未知" + concepts = [] + + try: + stock_info = ak.stock_individual_info_em(symbol=stock_code) + if not stock_info.empty and 'value' in stock_info.columns: + industry_row = stock_info[stock_info['item'] == '行业'] + if not industry_row.empty: + industry = industry_row['value'].iloc[0] + except: + pass + + # 热门板块和概念映射 + hot_sectors = { + '机器人': {'momentum': 0.85, 'limit_up_stocks': 18, 'active': True, + 'description': '人形机器人、工业自动化'}, + '半导体': {'momentum': 0.8, 'limit_up_stocks': 15, 'active': True, 'description': '芯片国产替代'}, + '人工智能': {'momentum': 0.75, 'limit_up_stocks': 12, 'active': True, 'description': 'AI大模型、算力'}, + '低空经济': {'momentum': 0.7, 'limit_up_stocks': 10, 'active': True, 'description': '无人机、eVTOL'}, + '新能源': {'momentum': 0.6, 'limit_up_stocks': 8, 'active': True, 'description': '光伏、储能'}, + '医药': {'momentum': 0.5, 'limit_up_stocks': 5, 'active': False, 'description': '创新药'} + } + + # 判断当前股票所属热门板块 + matched_sectors = [] + for sector, data in hot_sectors.items(): + if (sector in industry or + (stock_code == '600580' and sector in ['机器人', '低空经济']) or # 卧龙电驱特殊处理 + (stock_code == '300207' and sector in ['新能源'])): + matched_sectors.append({ + 'sector': sector, + 'momentum': data['momentum'], + 'limit_up_stocks': data['limit_up_stocks'], + 'is_active': data['active'], + 'description': data['description'] + }) + + # 计算综合共振分数 + if matched_sectors: + resonance_score = np.mean([sector['momentum'] for sector in matched_sectors]) + is_sector_hot = any(sector['is_active'] for sector in matched_sectors) + main_sector = max(matched_sectors, key=lambda x: x['momentum']) + else: + resonance_score = 0.5 + is_sector_hot = False + main_sector = {'sector': '传统行业', 'momentum': 0.5, 'description': '无热门概念'} + + analysis = { + 'industry': industry, + 'matched_sectors': matched_sectors, + 'main_sector': main_sector, + 'is_sector_hot': is_sector_hot, + 'resonance_score': resonance_score, + 'sector_count': len(matched_sectors) + } + + print(f"✅ 板块分析完成: {industry}, 匹配{len(matched_sectors)}个热门板块, 共振分数: {resonance_score:.2f}") + return analysis + + except Exception as e: + print(f"❌ 板块分析错误: {e}") + return self._get_default_sector_analysis() + + def analyze_macro_factors(self): + """ + 分析宏观因素 - 结合国内外政策 + """ + try: + print(f"🌍 分析宏观因素...") + + # 美国降息周期分析 - 基于最新信息 + us_rate_analysis = { + 'current_rate': 4.25, # 联邦基金利率目标区间4.00%-4.25%:cite[3] + 'trend': '降息周期', + 'recent_cut': '2025年9月降息25个基点', + 'expected_cuts_2025': 2, # 市场预期2025年还有两次降息:cite[7] + 'expected_cuts_2026': 2, + 'impact_on_emerging_markets': 'positive', + 'usd_index_support': 95.0, # 美元指数短期支撑位:cite[7] + 'analysis': '美联储开启宽松周期,利好全球流动性' + } + + # 国内政策因素 - 基于最新政策 + domestic_policy = { + 'monetary_policy': '稳健偏松', + 'fiscal_policy': '积极财政', + 'market_liquidity': '合理充裕', + 'industrial_policy': '设备更新、以旧换新', # 大规模设备更新政策:cite[5] + 'employment_policy': '稳就业政策加力', # 国务院稳就业政策:cite[8] + 'analysis': '政策组合拳发力,经济稳中向好' + } + + # 行业政策支持 + industry_policy = { + 'robot_policy': '机器人产业政策支持', + 'chip_policy': '国产替代加速推进', + 'AI_policy': '人工智能发展规划', + 'low_altitude': '低空经济发展规划' + } + + macro_analysis = { + 'us_rate_cycle': us_rate_analysis, + 'domestic_policy': domestic_policy, + 'industry_policy': industry_policy, + 'global_liquidity_outlook': '改善', + 'overall_macro_score': 0.75 # 宏观环境整体偏积极 + } + + print( + f"✅ 宏观分析完成: 美国{us_rate_analysis['trend']}, 国内政策积极, 宏观评分: {macro_analysis['overall_macro_score']:.2f}") + return macro_analysis + + except Exception as e: + print(f"❌ 宏观分析错误: {e}") + return self._get_default_macro_analysis() + + def analyze_company_fundamentals(self, stock_code): + """ + 分析公司基本面 - 针对特定股票 + """ + try: + print(f"🏢 分析公司基本面...") + + # 卧龙电驱特殊分析 + if stock_code == '600580': + fundamentals = { + 'company_name': '卧龙电驱', + 'business_areas': ['工业电机', '机器人关键部件', '航空电机', '新能源汽车驱动'], + 'recent_developments': [ + '与智元机器人实现双向持股,推进具身智能机器人技术研发:cite[5]', + '成立浙江龙飞电驱,专注航空电机业务:cite[5]', + '发布AI外骨骼机器人及灵巧手:cite[9]', + '布局高爆发关节模组、伺服驱动器等人形机器人关键部件:cite[5]' + ], + 'growth_drivers': [ + '设备更新政策推动工业电机需求:cite[5]', + '机器人产业快速发展', + '低空经济政策支持', + '出海战略加速' + ], + 'risk_factors': [ + '机器人业务营收占比仅2.71%,占比较低:cite[1]', + '工业需求景气度波动', + '原料价格波动风险' + ], + 'investment_rating': '积极关注', + 'fundamental_score': 0.7 + } + else: + # 其他股票的基础分析 + fundamentals = { + 'company_name': '未知', + 'business_areas': [], + 'recent_developments': [], + 'growth_drivers': [], + 'risk_factors': [], + 'investment_rating': '中性', + 'fundamental_score': 0.5 + } + + print(f"✅ 基本面分析完成: {fundamentals['company_name']}, 评分: {fundamentals['fundamental_score']:.2f}") + return fundamentals + + except Exception as e: + print(f"❌ 基本面分析错误: {e}") + return self._get_default_fundamental_analysis() + + def _calculate_trend_strength(self, df): + """计算趋势强度""" + if len(df) < 20: + return 0.5 + + ma_slope = (df['ma5'].iloc[-1] - df['ma5'].iloc[-20]) / df['ma5'].iloc[-20] + price_slope = (df['close'].iloc[-1] - df['close'].iloc[-20]) / df['close'].iloc[-20] + + volume_trend = df['volume'].iloc[-5:].mean() / df['volume'].iloc[-10:-5].mean() + + strength = (ma_slope * 0.4 + price_slope * 0.4 + min(volume_trend - 1, 0.2) * 0.2) + return max(0, min(1, strength * 10)) + + def _get_default_market_analysis(self): + return { + 'overall_is_main_uptrend': False, + 'overall_trend_strength': 0.5, + 'market_status': '未知', + 'detailed_analysis': {} + } + + def _get_default_sector_analysis(self): + return { + 'industry': '未知', + 'matched_sectors': [], + 'main_sector': {'sector': '未知', 'momentum': 0.5, 'description': ''}, + 'is_sector_hot': False, + 'resonance_score': 0.5, + 'sector_count': 0 + } + + def _get_default_macro_analysis(self): + return { + 'us_rate_cycle': {'trend': '未知', 'expected_cuts_2025': 0}, + 'domestic_policy': {'monetary_policy': '中性'}, + 'overall_macro_score': 0.5 + } + + def _get_default_fundamental_analysis(self): + return { + 'company_name': '未知', + 'business_areas': [], + 'recent_developments': [], + 'growth_drivers': [], + 'risk_factors': [], + 'investment_rating': '中性', + 'fundamental_score': 0.5 + } + + +# ==================== 增强预测函数 ==================== +def enhance_prediction_with_market_factors( + historical_df, + prediction_df, + stock_code, + market_analyzer +): + """ + 使用市场因素增强预测结果 - 多维度综合分析 + """ + print("\n🎯 使用多维度市场因素增强预测...") + + # 获取各类市场分析 + market_analysis = market_analyzer.analyze_market_trend() + sector_analysis = market_analyzer.analyze_sector_resonance(stock_code) + macro_analysis = market_analyzer.analyze_macro_factors() + fundamental_analysis = market_analyzer.analyze_company_fundamentals(stock_code) + + # 计算综合调整因子 + adjustment_factor = calculate_enhanced_adjustment_factor( + market_analysis, sector_analysis, macro_analysis, fundamental_analysis + ) + + print(f"📈 综合调整因子: {adjustment_factor:.4f}") + + # 应用调整到预测结果 + enhanced_prediction = prediction_df.copy() + + # 对价格预测进行调整 + price_columns = ['close', 'open', 'high', 'low'] + for col in price_columns: + if col in enhanced_prediction.columns: + # 使用更温和的调整,避免过度乐观或悲观 + adjusted_value = enhanced_prediction[col] * adjustment_factor + # 限制单次调整幅度在±10%以内 + change_ratio = adjusted_value / enhanced_prediction[col] + if change_ratio.max() > 1.1: + adjusted_value = enhanced_prediction[col] * 1.1 + elif change_ratio.min() < 0.9: + adjusted_value = enhanced_prediction[col] * 0.9 + enhanced_prediction[col] = adjusted_value + + # 对成交量进行调整 + if 'volume' in enhanced_prediction.columns: + volume_adjustment = 1 + (adjustment_factor - 1) * 0.3 # 成交量调整更温和 + enhanced_prediction['volume'] = enhanced_prediction['volume'] * volume_adjustment + + return enhanced_prediction, { + 'market_analysis': market_analysis, + 'sector_analysis': sector_analysis, + 'macro_analysis': macro_analysis, + 'fundamental_analysis': fundamental_analysis, + 'adjustment_factor': adjustment_factor + } + + +def calculate_enhanced_adjustment_factor(market_analysis, sector_analysis, macro_analysis, fundamental_analysis): + """ + 计算基于多维度市场因素的调整因子 - 更平衡的方法 + """ + base_factor = 1.0 + factors_log = [] + + # 1. 大盘趋势影响 (权重25%) + if market_analysis['overall_is_main_uptrend']: + trend_strength = market_analysis['overall_trend_strength'] + adjustment = 1 + trend_strength * 0.08 # 降低主升浪影响幅度 + base_factor *= adjustment + factors_log.append(f"大盘主升浪: +{trend_strength * 0.08:.3f}") + else: + trend_strength = market_analysis['overall_trend_strength'] + # 震荡市不一定悲观,只是增幅较小 + adjustment = 1 + (trend_strength - 0.5) * 0.04 + base_factor *= adjustment + factors_log.append(f"大盘震荡: {(trend_strength - 0.5) * 0.04:+.3f}") + + # 2. 板块共振影响 (权重25%) + resonance_score = sector_analysis['resonance_score'] + sector_count = sector_analysis['sector_count'] + + if sector_analysis['is_sector_hot']: + # 热门板块且有多个概念叠加 + sector_adjustment = 1 + resonance_score * 0.06 + min(sector_count * 0.01, 0.03) + base_factor *= sector_adjustment + factors_log.append( + f"热门板块({sector_count}个): +{resonance_score * 0.06 + min(sector_count * 0.01, 0.03):.3f}") + else: + # 非热门板块也有基础支撑 + base_factor *= (1 + (resonance_score - 0.5) * 0.02) + factors_log.append(f"一般板块: {(resonance_score - 0.5) * 0.02:+.3f}") + + # 3. 宏观因素影响 (权重20%) + macro_score = macro_analysis['overall_macro_score'] + macro_adjustment = 1 + (macro_score - 0.5) * 0.06 + base_factor *= macro_adjustment + factors_log.append(f"宏观环境: {(macro_score - 0.5) * 0.06:+.3f}") + + # 4. 美国降息周期特殊影响 (权重10%) + us_rate_trend = macro_analysis['us_rate_cycle']['trend'] + if us_rate_trend == '降息周期': + expected_cuts = macro_analysis['us_rate_cycle']['expected_cuts_2025'] + us_adjustment = 1 + expected_cuts * 0.015 # 降低单次降息影响 + base_factor *= us_adjustment + factors_log.append(f"美国降息: +{expected_cuts * 0.015:.3f}") + + # 5. 公司基本面影响 (权重20%) + fundamental_score = fundamental_analysis['fundamental_score'] + fundamental_adjustment = 1 + (fundamental_score - 0.5) * 0.08 + base_factor *= fundamental_adjustment + factors_log.append(f"基本面: {(fundamental_score - 0.5) * 0.08:+.3f}") + + # 输出调整因子详情 + print("🔍 调整因子详情:") + for log in factors_log: + print(f" {log}") + + # 限制调整幅度在更合理的范围内 (0.85 ~ 1.15) + final_factor = max(0.85, min(1.15, base_factor)) + + if final_factor != base_factor: + print(f"⚠️ 调整因子从 {base_factor:.3f} 限制到 {final_factor:.3f}") + + return final_factor + + +def create_comprehensive_market_report(enhancement_info, output_dir, stock_code): + """ + 创建综合市场分析报告 + """ + report = { + 'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S'), + 'stock_code': stock_code, + 'market_analysis': enhancement_info['market_analysis'], + 'sector_analysis': enhancement_info['sector_analysis'], + 'macro_analysis': enhancement_info['macro_analysis'], + 'fundamental_analysis': enhancement_info['fundamental_analysis'], + 'adjustment_factor': enhancement_info['adjustment_factor'], + 'analysis_summary': generate_analysis_summary(enhancement_info) + } + + # 保存报告 + report_file = os.path.join(output_dir, f'{stock_code}_comprehensive_analysis_report.json') + with open(report_file, 'w', encoding='utf-8') as f: + json.dump(report, f, ensure_ascii=False, indent=2) + + print(f"📋 综合分析报告已保存: {report_file}") + return report + + +def generate_analysis_summary(enhancement_info): + """ + 生成分析总结 + """ + market = enhancement_info['market_analysis'] + sector = enhancement_info['sector_analysis'] + macro = enhancement_info['macro_analysis'] + fundamental = enhancement_info['fundamental_analysis'] + + summary = { + 'overall_sentiment': '积极' if enhancement_info['adjustment_factor'] > 1.0 else '谨慎', + 'key_drivers': [], + 'main_risks': [], + 'investment_suggestion': '' + } + + # 关键驱动因素 + if market['overall_trend_strength'] > 0.6: + summary['key_drivers'].append('大盘趋势向好') + + if sector['is_sector_hot']: + summary['key_drivers'].append(f"热门板块:{sector['main_sector']['sector']}") + + if macro['overall_macro_score'] > 0.7: + summary['key_drivers'].append('宏观环境有利') + + if fundamental['fundamental_score'] > 0.6: + summary['key_drivers'].append('基本面稳健') + + # 主要风险 + if market['overall_trend_strength'] < 0.4: + summary['main_risks'].append('大盘趋势偏弱') + + if not sector['is_sector_hot']: + summary['main_risks'].append('非热门板块') + + if len(summary['key_drivers']) > len(summary['main_risks']): + summary['investment_suggestion'] = '可考虑逢低关注' + else: + summary['investment_suggestion'] = '建议谨慎操作' + + return summary + + +# ==================== 增强可视化函数 ==================== +def plot_comprehensive_prediction( + historical_df, + prediction_df, + future_dates, + stock_code, + stock_name, + output_dir, + enhancement_info=None +): + """ + 绘制综合预测图表 - 包含更多市场分析信息 + """ + ensure_output_directory(output_dir) + + # 设置配色 + colors = { + 'historical': '#1f77b4', + 'prediction': '#ff7f0e', + 'enhanced': '#2ca02c', + 'background': '#f8f9fa', + 'grid': '#e9ecef', + 'positive': '#2ecc71', + 'negative': '#e74c3c', + 'neutral': '#95a5a6' + } + + # 创建综合图表 + fig = plt.figure(figsize=(18, 14)) + gs = plt.GridSpec(4, 3, figure=fig, height_ratios=[2, 1, 1, 1]) + + # 1. 主价格图表 + ax1 = fig.add_subplot(gs[0, :]) + ax1.set_facecolor(colors['background']) + + # 2. 成交量图表 + ax2 = fig.add_subplot(gs[1, :]) + ax2.set_facecolor(colors['background']) + + # 3. 市场分析图表 + ax3 = fig.add_subplot(gs[2, 0]) + ax3.set_facecolor(colors['background']) + + ax4 = fig.add_subplot(gs[2, 1]) + ax4.set_facecolor(colors['background']) + + ax5 = fig.add_subplot(gs[2, 2]) + ax5.set_facecolor(colors['background']) + + # 4. 因素分析图表 + ax6 = fig.add_subplot(gs[3, :]) + ax6.set_facecolor(colors['background']) + + # 设置背景色 + fig.patch.set_facecolor('white') + + # 1. 价格图表 + historical_prices = historical_df.set_index('timestamps')['close'] + prediction_prices = prediction_df.set_index(pd.DatetimeIndex(future_dates))['close'] + + # 获取当前最新价格 + current_price = historical_prices.iloc[-1] + + # 智能Y轴范围计算 + all_prices = pd.concat([historical_prices, prediction_prices]) + data_min = all_prices.min() + data_max = all_prices.max() + + price_range = data_max - data_min + y_margin = price_range * 0.15 + + y_min = max(0, data_min - y_margin) + y_max = data_max + y_margin + + # 设置Y轴刻度 + y_interval = calculate_optimal_interval(y_min, y_max) + y_ticks = np.arange(round(y_min / y_interval) * y_interval, + round(y_max / y_interval) * y_interval + y_interval, + y_interval) + + # 绘制历史价格 + ax1.plot(historical_prices.index, historical_prices.values, + color=colors['historical'], linewidth=2, label='历史价格') + + # 绘制预测价格 + if len(prediction_prices) > 0: + # 连接点 + last_hist_date = historical_prices.index[-1] + last_hist_price = historical_prices.iloc[-1] + first_pred_date = prediction_prices.index[0] + + # 绘制连接线 + ax1.plot([last_hist_date, first_pred_date], + [last_hist_price, prediction_prices.iloc[0]], + color=colors['prediction'], linewidth=2.5, linestyle='-') + + # 绘制预测线 + ax1.plot(prediction_prices.index, prediction_prices.values, + color=colors['prediction'], linewidth=2.5, label='基础预测') + + # 绘制增强预测线 + if enhancement_info and 'enhanced_prediction' in enhancement_info: + enhanced_prices = enhancement_info['enhanced_prediction'].set_index(pd.DatetimeIndex(future_dates))['close'] + ax1.plot(enhanced_prices.index, enhanced_prices.values, + color=colors['enhanced'], linewidth=2.5, linestyle='--', label='增强预测') + + # 标记预测起点 + ax1.axvline(x=last_hist_date, color='red', linestyle='--', alpha=0.7, linewidth=1) + ax1.annotate('预测起点', xy=(last_hist_date, last_hist_price), + xytext=(10, 10), textcoords='offset points', + fontsize=10, fontweight='bold', + bbox=dict(boxstyle='round,pad=0.3', facecolor='white', alpha=0.8)) + + # 设置Y轴范围和刻度 + ax1.set_ylim(y_min, y_max) + ax1.set_yticks(y_ticks) + + ax1.set_ylabel('收盘价 (元)', fontsize=12, fontweight='bold') + ax1.legend(loc='upper left', fontsize=11) + ax1.grid(True, color=colors['grid'], alpha=0.7) + + title = f'{stock_name}({stock_code}) - 综合因素价格预测\n当前价: {current_price:.2f}元 | 增强因子: {enhancement_info["adjustment_factor"]:.3f}' if enhancement_info else f'{stock_name}({stock_code}) - 价格预测\n当前价: {current_price:.2f}元' + ax1.set_title(title, fontsize=14, fontweight='bold', pad=20) + + # 设置x轴格式 + ax1.xaxis.set_major_formatter(plt.matplotlib.dates.DateFormatter('%Y-%m-%d')) + plt.setp(ax1.xaxis.get_majorticklabels(), rotation=45) + + # 2. 成交量图表 + historical_volume = historical_df.set_index('timestamps')['volume'] + prediction_volume = prediction_df.set_index(pd.DatetimeIndex(future_dates))['volume'] + + # 计算相对成交量(标准化) + hist_volume_norm = historical_volume / historical_volume.max() + if len(prediction_volume) > 0: + pred_volume_norm = prediction_volume / historical_volume.max() + + # 绘制历史成交量 + ax2.bar(historical_volume.index, hist_volume_norm.values, + alpha=0.6, color=colors['historical'], label='历史成交量') + + # 绘制预测成交量 + if len(prediction_volume) > 0: + ax2.bar(prediction_volume.index, pred_volume_norm.values, + alpha=0.6, color=colors['prediction'], label='预测成交量') + + ax2.set_ylabel('相对成交量', fontsize=12, fontweight='bold') + ax2.legend(loc='upper left', fontsize=11) + ax2.grid(True, color=colors['grid'], alpha=0.7) + ax2.set_ylim(0, 1.2) + + # 设置x轴格式 + ax2.xaxis.set_major_formatter(plt.matplotlib.dates.DateFormatter('%Y-%m-%d')) + plt.setp(ax2.xaxis.get_majorticklabels(), rotation=45) + + # 3. 市场分析子图 + if enhancement_info: + # 因素权重饼图 + factors = ['大盘趋势', '板块共振', '宏观环境', '美国降息', '基本面'] + weights = [25, 25, 20, 10, 20] + colors_pie = [colors['historical'], colors['prediction'], colors['enhanced'], '#f39c12', '#9b59b6'] + + ax3.pie(weights, labels=factors, autopct='%1.0f%%', colors=colors_pie, startangle=90) + ax3.set_title('因素权重分配', fontweight='bold', fontsize=11) + + # 因素评分柱状图 + scores = [ + enhancement_info['market_analysis']['overall_trend_strength'], + enhancement_info['sector_analysis']['resonance_score'], + enhancement_info['macro_analysis']['overall_macro_score'], + 0.7 if enhancement_info['macro_analysis']['us_rate_cycle']['trend'] == '降息周期' else 0.3, + enhancement_info['fundamental_analysis']['fundamental_score'] + ] + + x_pos = np.arange(len(factors)) + bars = ax4.bar(x_pos, scores, color=colors_pie, alpha=0.7) + ax4.set_xticks(x_pos) + ax4.set_xticklabels(factors, rotation=45, fontsize=9) + ax4.set_ylim(0, 1) + ax4.set_ylabel('评分', fontsize=10) + ax4.set_title('各因素当前评分', fontweight='bold', fontsize=11) + ax4.grid(True, alpha=0.3) + + # 在柱状图上显示数值 + for i, bar in enumerate(bars): + height = bar.get_height() + ax4.text(bar.get_x() + bar.get_width() / 2., height + 0.01, + f'{height:.2f}', ha='center', va='bottom', fontsize=8) + + # 市场状态总结 + market_status = enhancement_info['market_analysis']['market_status'] + sector_status = "热门" if enhancement_info['sector_analysis']['is_sector_hot'] else "一般" + macro_status = "有利" if enhancement_info['macro_analysis']['overall_macro_score'] > 0.6 else "不利" + + summary_text = f"""市场状态总结: + +大盘趋势: {market_status} +板块热度: {sector_status} +宏观环境: {macro_status} +美国利率: {enhancement_info['macro_analysis']['us_rate_cycle']['trend']} +综合评分: {enhancement_info['adjustment_factor']:.3f} + +投资建议: {enhancement_info['fundamental_analysis']['investment_rating']}""" + + ax5.text(0.1, 0.9, summary_text, transform=ax5.transAxes, fontsize=10, + verticalalignment='top', linespacing=1.5) + ax5.set_title('市场状态总结', fontweight='bold', fontsize=11) + ax5.set_xticks([]) + ax5.set_yticks([]) + ax5.spines['top'].set_visible(False) + ax5.spines['right'].set_visible(False) + ax5.spines['bottom'].set_visible(False) + ax5.spines['left'].set_visible(False) + + # 4. 详细因素分析 + if 'analysis_summary' in enhancement_info: + summary = enhancement_info['analysis_summary'] + drivers_text = "\n".join([f"• {driver}" for driver in summary['key_drivers']]) if summary[ + 'key_drivers'] else "• 暂无明显驱动" + risks_text = "\n".join([f"• {risk}" for risk in summary['main_risks']]) if summary[ + 'main_risks'] else "• 风险可控" + + detail_text = f"""关键驱动因素: +{drivers_text} + +主要风险提示: +{risks_text} + +总体情绪: {summary['overall_sentiment']} +建议: {summary['investment_suggestion']}""" + + ax6.text(0.02, 0.95, detail_text, transform=ax6.transAxes, fontsize=9, + verticalalignment='top', linespacing=1.3) + ax6.set_title('详细因素分析', fontweight='bold', fontsize=11) + ax6.set_xticks([]) + ax6.set_yticks([]) + ax6.spines['top'].set_visible(False) + ax6.spines['right'].set_visible(False) + ax6.spines['bottom'].set_visible(False) + ax6.spines['left'].set_visible(False) + + plt.tight_layout() + + # 保存图片 + chart_filename = os.path.join(output_dir, f'{stock_code}_comprehensive_prediction.png') + plt.savefig(chart_filename, dpi=300, bbox_inches='tight', facecolor='white') + print(f"📊 综合预测图表已保存: {chart_filename}") + + plt.show() + + return historical_prices, prediction_prices + + +# ==================== 主预测函数 ==================== +def run_comprehensive_kronos_prediction(stock_code, stock_name, data_dir, pred_days, output_dir, history_years=1): + """ + 运行综合版Kronos模型预测流程 + """ + print(f"\n🎯 开始 {stock_name}({stock_code}) 综合版Kronos模型价格预测") + print("=" * 60) + + # 初始化增强版市场分析器 + market_analyzer = EnhancedMarketFactorAnalyzer() + + try: + # 1. 获取数据 + print("\n步骤1: 获取股票数据...") + success, csv_file_path = get_stock_data(stock_code, data_dir) + if not success: + print("❌ 无法获取股票数据,预测终止") + return + + # 2. 加载模型和分词器 + print("\n步骤2: 加载Kronos模型和分词器...") + try: + tokenizer = KronosTokenizer.from_pretrained("NeoQuasar/Kronos-Tokenizer-base") + model = Kronos.from_pretrained("NeoQuasar/Kronos-base") + print("✅ 模型加载完成 - 使用Kronos-base模型") + except Exception as e: + print(f"❌ 模型加载失败: {e}") + print("⚠️ 预测功能不可用,请检查模型安装") + return + + # 3. 实例化预测器 + print("步骤3: 初始化预测器...") + predictor = KronosPredictor(model, tokenizer, device="cuda:0", max_context=512) + print("✅ 预测器初始化完成") + + # 4. 准备数据 + print("步骤4: 准备股票数据...") + df = prepare_stock_data(csv_file_path, stock_code, history_years) + + # 5. 计算预测参数 + print("步骤5: 计算预测参数...") + lookback, pred_len = calculate_prediction_parameters(df, target_days=pred_days) + + if pred_len <= 0: + print("❌ 数据量不足,无法进行预测") + return + + print(f"✅ 最终参数 - 回看期: {lookback}, 预测期: {pred_len}") + + # 6. 准备输入数据 + print("步骤6: 准备输入数据...") + x_df = df.loc[-lookback:, ['open', 'high', 'low', 'close', 'volume', 'amount']].reset_index(drop=True) + x_timestamp = df.loc[-lookback:, 'timestamps'].reset_index(drop=True) + + # 生成未来日期 + last_historical_date = df['timestamps'].iloc[-1] + future_dates = generate_future_dates(last_historical_date, pred_len) + + print(f"输入数据形状: {x_df.shape}") + print(f"历史数据时间范围: {x_timestamp.iloc[0]} 到 {x_timestamp.iloc[-1]}") + print(f"预测时间范围: {future_dates[0]} 到 {future_dates[-1]}") + + # 7. 执行基础预测 + print("步骤7: 执行基础价格预测...") + pred_df = predictor.predict( + df=x_df, + x_timestamp=x_timestamp, + y_timestamp=pd.Series(future_dates), + pred_len=pred_len, + T=1.0, + top_p=0.9, + sample_count=1, + verbose=True + ) + + print("✅ 基础预测完成") + print("预测数据前5行:") + print(pred_df.head()) + + # 8. 使用多维度市场因素增强预测 + print("步骤8: 应用多维度市场因素增强预测...") + enhanced_pred_df, enhancement_info = enhance_prediction_with_market_factors( + df.loc[-lookback:].reset_index(drop=True), + pred_df, + stock_code, + market_analyzer + ) + + # 将增强预测结果添加到信息中 + enhancement_info['enhanced_prediction'] = enhanced_pred_df + + # 9. 创建综合市场分析报告 + market_report = create_comprehensive_market_report(enhancement_info, output_dir, stock_code) + + # 10. 可视化结果 + print("步骤9: 生成综合版可视化图表...") + historical_df = df.loc[-lookback:].reset_index(drop=True) + hist_prices, base_pred_prices = plot_comprehensive_prediction( + historical_df, pred_df, future_dates, stock_code, stock_name, output_dir, enhancement_info + ) + + # 11. 生成综合预测报告 + print("步骤10: 生成综合预测报告...") + if len(enhanced_pred_df) > 0: + current_price = hist_prices.iloc[-1] + base_predicted_price = base_pred_prices.iloc[-1] if len(base_pred_prices) > 0 else current_price + enhanced_predicted_price = enhanced_pred_df.set_index(pd.DatetimeIndex(future_dates))['close'].iloc[-1] + + base_change_pct = (base_predicted_price / current_price - 1) * 100 + enhanced_change_pct = (enhanced_predicted_price / current_price - 1) * 100 + + print(f"\n📈 综合版Kronos模型预测报告") + print("=" * 70) + print(f"股票: {stock_name}({stock_code})") + print(f"当前价格: {current_price:.2f} 元") + print(f"基础预测价格: {base_predicted_price:.2f} 元 ({base_change_pct:+.2f}%)") + print(f"增强预测价格: {enhanced_predicted_price:.2f} 元 ({enhanced_change_pct:+.2f}%)") + print(f"市场因素调整因子: {enhancement_info['adjustment_factor']:.4f}") + print(f"大盘状态: {enhancement_info['market_analysis']['market_status']}") + print( + f"板块共振: {enhancement_info['sector_analysis']['main_sector']['sector']} (分数: {enhancement_info['sector_analysis']['resonance_score']:.2f})") + print(f"宏观环境: 美国{enhancement_info['macro_analysis']['us_rate_cycle']['trend']}") + print(f"公司评级: {enhancement_info['fundamental_analysis']['investment_rating']}") + print(f"预测期间: {pred_len} 个交易日") + + # 输出关键因素 + print(f"\n🔑 关键影响因素:") + for driver in enhancement_info['analysis_summary']['key_drivers']: + print(f" ✅ {driver}") + for risk in enhancement_info['analysis_summary']['main_risks']: + print(f" ⚠️ {risk}") + print(f" 💡 投资建议: {enhancement_info['analysis_summary']['investment_suggestion']}") + + # 保存详细预测数据 + prediction_details = pd.DataFrame({ + '日期': future_dates, + '基础预测收盘价': base_pred_prices.values if len(base_pred_prices) > 0 else [current_price] * len( + future_dates), + '增强预测收盘价': enhanced_pred_df['close'].values, + '预测成交量': enhanced_pred_df['volume'].values + }) + + prediction_file = os.path.join(output_dir, f'{stock_code}_comprehensive_predictions.csv') + prediction_details.to_csv(prediction_file, index=False, encoding='utf-8-sig') + print(f"💾 详细预测数据已保存: {prediction_file}") + + print(f"\n🎉 {stock_name}({stock_code}) 综合版Kronos模型预测完成!") + + except Exception as e: + print(f"❌ 预测过程中出现错误: {e}") + import traceback + traceback.print_exc() + + +# ==================== 主函数 ==================== +def main(): + """ + 主函数:综合版Kronos模型股票预测系统 + """ + # ==================== 配置参数 ==================== + STOCK_CONFIG = { + "stock_code": "603288", + "stock_name": "海天味业", + "data_dir": r"D:\lianghuajiaoyi\Kronos\examples\data", + "pred_days": 60, + "output_dir": r"D:\lianghuajiaoyi\Kronos\examples\yuce", + "history_years": 1 + } + + print("🤖 综合版Kronos模型股票价格预测系统") + print("=" * 50) + print("📊 新增功能: 多维度市场因素分析") + print("🎯 包含: 大盘趋势 + 板块共振 + 宏观政策 + 公司基本面") + print("🚀 使用模型: Kronos-base (更适合3070Ti显卡)") + print(f"当前预测股票: {STOCK_CONFIG['stock_name']}({STOCK_CONFIG['stock_code']})") + print(f"预测天数: {STOCK_CONFIG['pred_days']} 天") + print(f"输出目录: {STOCK_CONFIG['output_dir']}") + print() + + # 运行综合版Kronos模型预测流程 + run_comprehensive_kronos_prediction(**STOCK_CONFIG) + + print(f"\n💡 提示:综合版模型已整合多维度市场环境分析因子") + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/examples/prediction_new_GUI.py b/examples/prediction_new_GUI.py new file mode 100644 index 0000000..2eab618 --- /dev/null +++ b/examples/prediction_new_GUI.py @@ -0,0 +1,1625 @@ +import pandas as pd +import matplotlib.pyplot as plt +import numpy as np +import sys +import os +from datetime import datetime, timedelta +import warnings +import requests +import json +import time +import random +import akshare as ak +from typing import Dict, List, Tuple, Optional +import tkinter as tk +from tkinter import ttk, messagebox, filedialog +import threading +from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg +import matplotlib.dates as mdates +import matplotlib.ticker as ticker + +warnings.filterwarnings('ignore') + +# 添加项目路径以便导入自定义模块 +sys.path.append("../") +try: + from model import Kronos, KronosTokenizer, KronosPredictor +except ImportError: + print("⚠️ 无法导入Kronos模型,预测功能将不可用") + +# 设置中文字体 +plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签 +plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号 + + +class StockPredictorGUI: + """股票预测图形界面""" + + def __init__(self, root): + self.root = root + self.root.title("Kronos股票预测系统") + self.root.geometry("800x600") + self.root.configure(bg='#f0f0f0') + + # 初始化市场分析器 + self.market_analyzer = EnhancedMarketFactorAnalyzer() + + # 创建界面 + self.create_widgets() + + # 默认配置 + self.default_config = { + "stock_code": "600580", + "stock_name": "卧龙电驱", + "data_dir": r"D:\lianghuajiaoyi\Kronos\examples\data", + "output_dir": r"D:\lianghuajiaoyi\Kronos\examples\yuce", + "pred_days": 60, + "history_years": 1 + } + + def create_widgets(self): + """创建界面组件""" + # 主标题 + title_label = tk.Label( + self.root, + text="🤖 Kronos股票预测系统", + font=("Arial", 16, "bold"), + bg='#f0f0f0', + fg='#2c3e50' + ) + title_label.pack(pady=10) + + # 说明标签 + desc_label = tk.Label( + self.root, + text="基于Kronos模型的多维度股票价格预测系统", + font=("Arial", 10), + bg='#f0f0f0', + fg='#7f8c8d' + ) + desc_label.pack(pady=5) + + # 创建主框架 + main_frame = tk.Frame(self.root, bg='#f0f0f0') + main_frame.pack(fill=tk.BOTH, expand=True, padx=20, pady=10) + + # 输入框架 + input_frame = tk.LabelFrame(main_frame, text="股票参数设置", font=("Arial", 11, "bold"), + bg='#f0f0f0', fg='#2c3e50') + input_frame.pack(fill=tk.X, pady=10) + + # 股票代码输入 + tk.Label(input_frame, text="股票代码:", bg='#f0f0f0', font=("Arial", 10)).grid(row=0, column=0, sticky=tk.W, + padx=5, pady=5) + self.stock_code_var = tk.StringVar(value="600580") + stock_code_entry = tk.Entry(input_frame, textvariable=self.stock_code_var, font=("Arial", 10), width=15) + stock_code_entry.grid(row=0, column=1, padx=5, pady=5) + + # 股票名称输入 + tk.Label(input_frame, text="股票名称:", bg='#f0f0f0', font=("Arial", 10)).grid(row=0, column=2, sticky=tk.W, + padx=5, pady=5) + self.stock_name_var = tk.StringVar(value="卧龙电驱") + stock_name_entry = tk.Entry(input_frame, textvariable=self.stock_name_var, font=("Arial", 10), width=15) + stock_name_entry.grid(row=0, column=3, padx=5, pady=5) + + # 预测天数 + tk.Label(input_frame, text="预测天数:", bg='#f0f0f0', font=("Arial", 10)).grid(row=1, column=0, sticky=tk.W, + padx=5, pady=5) + self.pred_days_var = tk.StringVar(value="60") + pred_days_entry = tk.Entry(input_frame, textvariable=self.pred_days_var, font=("Arial", 10), width=15) + pred_days_entry.grid(row=1, column=1, padx=5, pady=5) + + # 历史数据年限 + tk.Label(input_frame, text="历史年限:", bg='#f0f0f0', font=("Arial", 10)).grid(row=1, column=2, sticky=tk.W, + padx=5, pady=5) + self.history_years_var = tk.StringVar(value="1") + history_years_entry = tk.Entry(input_frame, textvariable=self.history_years_var, font=("Arial", 10), width=15) + history_years_entry.grid(row=1, column=3, padx=5, pady=5) + + # 目录设置框架 + dir_frame = tk.LabelFrame(main_frame, text="目录设置", font=("Arial", 11, "bold"), + bg='#f0f0f0', fg='#2c3e50') + dir_frame.pack(fill=tk.X, pady=10) + + # 数据目录 + tk.Label(dir_frame, text="数据目录:", bg='#f0f0f0', font=("Arial", 10)).grid(row=0, column=0, sticky=tk.W, + padx=5, pady=5) + self.data_dir_var = tk.StringVar(value=r"D:\lianghuajiaoyi\Kronos\examples\data") + data_dir_entry = tk.Entry(dir_frame, textvariable=self.data_dir_var, font=("Arial", 10), width=40) + data_dir_entry.grid(row=0, column=1, padx=5, pady=5) + tk.Button(dir_frame, text="浏览", command=self.browse_data_dir, font=("Arial", 9)).grid(row=0, column=2, padx=5, + pady=5) + + # 输出目录 + tk.Label(dir_frame, text="输出目录:", bg='#f0f0f0', font=("Arial", 10)).grid(row=1, column=0, sticky=tk.W, + padx=5, pady=5) + self.output_dir_var = tk.StringVar(value=r"D:\lianghuajiaoyi\Kronos\examples\yuce") + output_dir_entry = tk.Entry(dir_frame, textvariable=self.output_dir_var, font=("Arial", 10), width=40) + output_dir_entry.grid(row=1, column=1, padx=5, pady=5) + tk.Button(dir_frame, text="浏览", command=self.browse_output_dir, font=("Arial", 9)).grid(row=1, column=2, + padx=5, pady=5) + + # 功能按钮框架 + button_frame = tk.Frame(main_frame, bg='#f0f0f0') + button_frame.pack(pady=20) + + # 预测按钮 + self.predict_button = tk.Button( + button_frame, + text="🚀 开始预测", + command=self.start_prediction, + font=("Arial", 12, "bold"), + bg='#3498db', + fg='white', + width=15, + height=2 + ) + self.predict_button.pack(side=tk.LEFT, padx=10) + + # 重置按钮 + reset_button = tk.Button( + button_frame, + text="🔄 重置", + command=self.reset_fields, + font=("Arial", 10), + bg='#95a5a6', + fg='white', + width=10, + height=2 + ) + reset_button.pack(side=tk.LEFT, padx=10) + + # 退出按钮 + exit_button = tk.Button( + button_frame, + text="❌ 退出", + command=self.root.quit, + font=("Arial", 10), + bg='#e74c3c', + fg='white', + width=10, + height=2 + ) + exit_button.pack(side=tk.LEFT, padx=10) + + # 进度显示 + self.progress_frame = tk.LabelFrame(main_frame, text="预测进度", font=("Arial", 11, "bold"), + bg='#f0f0f0', fg='#2c3e50') + self.progress_frame.pack(fill=tk.X, pady=10) + + self.progress_var = tk.StringVar(value="等待开始预测...") + progress_label = tk.Label(self.progress_frame, textvariable=self.progress_var, bg='#f0f0f0', + font=("Arial", 10), wraplength=700, justify=tk.LEFT) + progress_label.pack(padx=10, pady=10, fill=tk.X) + + # 进度条 + self.progress_bar = ttk.Progressbar(self.progress_frame, mode='indeterminate') + self.progress_bar.pack(fill=tk.X, padx=10, pady=5) + + # 结果展示区域 + self.result_frame = tk.LabelFrame(main_frame, text="预测结果", font=("Arial", 11, "bold"), + bg='#f0f0f0', fg='#2c3e50') + self.result_frame.pack(fill=tk.BOTH, expand=True, pady=10) + + self.result_text = tk.Text(self.result_frame, height=8, font=("Arial", 9), wrap=tk.WORD) + scrollbar = tk.Scrollbar(self.result_frame, command=self.result_text.yview) + self.result_text.configure(yscrollcommand=scrollbar.set) + self.result_text.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=5, pady=5) + scrollbar.pack(side=tk.RIGHT, fill=tk.Y, pady=5) + + def browse_data_dir(self): + """浏览数据目录""" + directory = filedialog.askdirectory() + if directory: + self.data_dir_var.set(directory) + + def browse_output_dir(self): + """浏览输出目录""" + directory = filedialog.askdirectory() + if directory: + self.output_dir_var.set(directory) + + def reset_fields(self): + """重置输入字段""" + self.stock_code_var.set("600580") + self.stock_name_var.set("卧龙电驱") + self.pred_days_var.set("60") + self.history_years_var.set("1") + self.data_dir_var.set(r"D:\lianghuajiaoyi\Kronos\examples\data") + self.output_dir_var.set(r"D:\lianghuajiaoyi\Kronos\examples\yuce") + self.result_text.delete(1.0, tk.END) + self.progress_var.set("等待开始预测...") + + def start_prediction(self): + """开始预测""" + # 验证输入 + if not self.validate_inputs(): + return + + # 禁用预测按钮 + self.predict_button.config(state=tk.DISABLED) + + # 清空结果区域 + self.result_text.delete(1.0, tk.END) + + # 开始进度条 + self.progress_bar.start() + + # 在新线程中运行预测 + prediction_thread = threading.Thread(target=self.run_prediction) + prediction_thread.daemon = True + prediction_thread.start() + + def validate_inputs(self): + """验证输入参数""" + try: + stock_code = self.stock_code_var.get().strip() + stock_name = self.stock_name_var.get().strip() + pred_days = int(self.pred_days_var.get()) + history_years = int(self.history_years_var.get()) + + if not stock_code: + messagebox.showerror("错误", "请输入股票代码") + return False + + if not stock_name: + messagebox.showerror("错误", "请输入股票名称") + return False + + if pred_days <= 0 or pred_days > 365: + messagebox.showerror("错误", "预测天数应在1-365天之间") + return False + + if history_years <= 0 or history_years > 10: + messagebox.showerror("错误", "历史年限应在1-10年之间") + return False + + return True + + except ValueError: + messagebox.showerror("错误", "请输入有效的数字") + return False + + def run_prediction(self): + """运行预测流程""" + try: + # 获取输入参数 + stock_code = self.stock_code_var.get().strip() + stock_name = self.stock_name_var.get().strip() + pred_days = int(self.pred_days_var.get()) + history_years = int(self.history_years_var.get()) + data_dir = self.data_dir_var.get() + output_dir = self.output_dir_var.get() + + # 更新进度 + self.update_progress("🎯 开始股票预测流程...") + + # 运行预测 + success, result = run_comprehensive_prediction_gui( + stock_code, stock_name, data_dir, pred_days, output_dir, history_years, + progress_callback=self.update_progress, + result_callback=self.update_result + ) + + if success: + self.update_progress("✅ 预测完成!") + messagebox.showinfo("完成", f"{stock_name}({stock_code})预测完成!\n图表已保存到输出目录。") + else: + self.update_progress("❌ 预测失败") + messagebox.showerror("错误", f"预测失败: {result}") + + except Exception as e: + self.update_progress(f"❌ 预测过程出现错误: {str(e)}") + messagebox.showerror("错误", f"预测过程出现错误: {str(e)}") + finally: + # 重新启用预测按钮 + self.root.after(0, lambda: self.predict_button.config(state=tk.NORMAL)) + # 停止进度条 + self.root.after(0, self.progress_bar.stop) + + def update_progress(self, message): + """更新进度信息""" + self.root.after(0, lambda: self.progress_var.set(message)) + print(message) # 同时在控制台输出 + + def update_result(self, message): + """更新结果信息""" + self.root.after(0, lambda: self.result_text.insert(tk.END, message + "\n")) + self.root.after(0, lambda: self.result_text.see(tk.END)) + + +# ==================== 基础数据获取函数 ==================== +def ensure_output_directory(output_dir): + """确保输出目录存在,如果不存在则创建""" + if not os.path.exists(output_dir): + os.makedirs(output_dir) + print(f"✅ 创建输出目录: {output_dir}") + return output_dir + + +def fetch_real_stock_data(stock_code, period="daily", adjust="qfq"): + """ + 使用AKShare获取真实股票数据 + """ + try: + print(f"📡 正在通过AKShare获取 {stock_code} 的真实股票数据...") + + # 获取股票数据 + df = ak.stock_zh_a_hist(symbol=stock_code, period=period, adjust=adjust) + + if df is None or df.empty: + print(f"❌ 未获取到 {stock_code} 的数据") + return None + + # 重命名列以统一格式 + column_mapping = { + '日期': 'timestamps', + '开盘': 'open', + '收盘': 'close', + '最高': 'high', + '最低': 'low', + '成交量': 'volume', + '成交额': 'amount', + '振幅': 'amplitude', + '涨跌幅': 'pct_chg', + '涨跌额': 'change_amount', + '换手率': 'turnover' + } + + # 只映射存在的列 + actual_mapping = {k: v for k, v in column_mapping.items() if k in df.columns} + df = df.rename(columns=actual_mapping) + + # 确保时间戳格式正确 + df['timestamps'] = pd.to_datetime(df['timestamps']) + df = df.sort_values('timestamps').reset_index(drop=True) + + # 添加股票代码列 + df['stock_code'] = stock_code + + print(f"✅ 成功获取 {len(df)} 条真实数据") + print(f"📈 最新收盘价: {df['close'].iloc[-1]:.2f}元, 涨跌幅: {df['pct_chg'].iloc[-1]:.2f}%") + print(f"📅 时间范围: {df['timestamps'].min()} 到 {df['timestamps'].max()}") + + return df + + except Exception as e: + print(f"❌ AKShare数据获取失败: {e}") + return None + + +def get_stock_data_with_retry_all_history(stock_code="600580", retry_count=2): + """ + 优化的数据获取函数 - 优先使用真实API数据 + """ + print(f"🔄 尝试获取股票 {stock_code} 的真实历史数据...") + + # 优先使用AKShare获取真实数据 + df = fetch_real_stock_data(stock_code, "daily", "qfq") + + if df is not None: + return df + else: + print("⚠️ 真实数据获取失败,使用基于真实价格的模拟数据...") + return create_realistic_fallback_data(stock_code) + + +def create_realistic_fallback_data(stock_code="600580"): + """ + 基于真实价格的备用数据生成函数 + """ + # 基于真实市场价格的参考数据 + real_stock_references = { + '600580': {'name': '卧龙电驱', 'current_price': 15.20, 'range': (12.0, 20.0)}, + '300207': {'name': '欣旺达', 'current_price': 33.79, 'range': (28.0, 38.0)}, + '300418': {'name': '昆仑万维', 'current_price': 48.59, 'range': (40.0, 55.0)}, + '002354': {'name': '天娱数科', 'current_price': 15.20, 'range': (12.0, 20.0)}, + '000001': {'name': '平安银行', 'current_price': 12.50, 'range': (10.0, 16.0)}, + '600036': {'name': '招商银行', 'current_price': 35.80, 'range': (30.0, 42.0)}, + } + + stock_info = real_stock_references.get(stock_code, { + 'name': '未知股票', + 'current_price': 20.0, + 'range': (15.0, 25.0) + }) + + # 生成最近1年的交易日数据 + end_date = datetime.now() + start_date = end_date - timedelta(days=365) + dates = pd.bdate_range(start=start_date, end=end_date, freq='B') + + # 生成基于真实价格的价格序列 + np.random.seed(42) + n_points = len(dates) + + # 从当前价格反向生成历史价格 + current_price = stock_info['current_price'] + min_price, max_price = stock_info['range'] + + # 反向生成价格序列 + prices = [current_price] + for i in range(1, n_points): + volatility = 0.02 + historical_return = np.random.normal(-0.0002, volatility) + + prev_price = prices[0] * (1 + historical_return) + prev_price = max(min_price * 0.9, min(max_price * 1.1, prev_price)) + prices.insert(0, prev_price) + + # 生成OHLC数据 + stock_data = [] + for i, date in enumerate(dates): + close_price = prices[i] + + daily_volatility = abs(np.random.normal(0, 0.015)) + open_price = close_price * (1 + np.random.normal(0, 0.005)) + high_price = max(open_price, close_price) * (1 + daily_volatility) + low_price = min(open_price, close_price) * (1 - daily_volatility) + + high_price = max(open_price, close_price, low_price, high_price) + low_price = min(open_price, close_price, high_price, low_price) + + volume = int(abs(np.random.normal(1500000, 400000))) + amount = volume * close_price + + if i > 0: + pct_chg = ((close_price - prices[i - 1]) / prices[i - 1]) * 100 + change_amount = close_price - prices[i - 1] + else: + pct_chg = 0 + change_amount = 0 + + stock_data.append({ + 'timestamps': date, + 'stock_code': stock_code, + 'open': round(open_price, 2), + 'close': round(close_price, 2), + 'high': round(high_price, 2), + 'low': round(low_price, 2), + 'volume': volume, + 'amount': round(amount, 2), + 'amplitude': round(((high_price - low_price) / open_price) * 100, 2), + 'pct_chg': round(pct_chg, 2), + 'change_amount': round(change_amount, 2), + 'turnover': round(np.random.uniform(3.0, 8.0), 2) + }) + + df = pd.DataFrame(stock_data) + print(f"✅ 已生成基于真实价格的备用数据 {len(df)} 条") + return df + + +def save_all_history_stock_data(df, stock_code, save_dir): + """ + 保存股票数据到指定目录 + """ + if df is not None and not df.empty: + os.makedirs(save_dir, exist_ok=True) + csv_file = os.path.join(save_dir, f"{stock_code}_stock_data.csv") + df_reset = df.reset_index() + df_reset.to_csv(csv_file, encoding='utf-8-sig', index=False) + print(f"📁 股票数据已保存: {csv_file}") + return True + return False + + +def get_stock_data(stock_code, data_dir): + """ + 获取股票数据,如果数据文件不存在则从API获取真实数据 + """ + csv_file_path = os.path.join(data_dir, f"{stock_code}_stock_data.csv") + + if os.path.exists(csv_file_path): + print(f"📁 使用现有数据文件: {csv_file_path}") + return True, csv_file_path + else: + print(f"📡 数据文件不存在,从API获取真实数据...") + df = get_stock_data_with_retry_all_history(stock_code) + + if df is not None and not df.empty: + save_all_history_stock_data(df, stock_code, data_dir) + return True, csv_file_path + else: + print(f"❌ 无法获取股票数据") + return False, None + + +def prepare_stock_data(csv_file_path, stock_code, history_years=1): + """ + 准备股票数据,转换为Kronos模型需要的格式 + """ + print(f"正在加载和预处理股票 {stock_code} 数据...") + + # 读取CSV文件 + df = pd.read_csv(csv_file_path, encoding='utf-8-sig') + + # 标准化列名 + column_mapping = { + '日期': 'timestamps', + '开盘价': 'open', + '最高价': 'high', + '最低价': 'low', + '收盘价': 'close', + '成交量': 'volume', + '成交额': 'amount', + '开盘': 'open', + '收盘': 'close', + '最高': 'high', + '最低': 'low' + } + + actual_mapping = {k: v for k, v in column_mapping.items() if k in df.columns} + df = df.rename(columns=actual_mapping) + + # 确保时间戳列存在并转换为datetime格式 + if 'timestamps' not in df.columns: + if df.index.name == '日期': + df = df.reset_index() + df = df.rename(columns={'日期': 'timestamps'}) + + df['timestamps'] = pd.to_datetime(df['timestamps']) + df = df.sort_values('timestamps').reset_index(drop=True) + + # 根据历史年限筛选数据 + if history_years > 0: + cutoff_date = datetime.now() - timedelta(days=history_years * 365) + original_count = len(df) + df = df[df['timestamps'] >= cutoff_date] + print(f"📅 使用最近 {history_years} 年数据: {len(df)} 条记录 (从 {original_count} 条中筛选)") + + # 数据验证 + print(f"🔍 数据验证 - 最近5个交易日收盘价:") + recent_prices = df[['timestamps', 'close']].tail() + for _, row in recent_prices.iterrows(): + print(f" {row['timestamps'].strftime('%Y-%m-%d')}: {row['close']:.2f}元") + + current_price = df['close'].iloc[-1] + print(f"✅ 数据加载完成,共 {len(df)} 条记录") + print(f"时间范围: {df['timestamps'].min()} 到 {df['timestamps'].max()}") + print(f"价格范围: {df['close'].min():.2f} - {df['close'].max():.2f}") + print(f"当前价格: {current_price:.2f}元") + + return df + + +def calculate_prediction_parameters(df, target_days=60): + """ + 根据目标预测天数计算合适的参数 + """ + # 计算平均交易日数量 + total_days = (df['timestamps'].max() - df['timestamps'].min()).days + trading_days = len(df) + trading_ratio = trading_days / total_days if total_days > 0 else 0.7 + + # 计算目标预测的交易日数量 + pred_trading_days = int(target_days * trading_ratio) + + # 设置回看期数 + max_lookback = int(len(df) * 0.7) + lookback = min(pred_trading_days * 3, max_lookback, len(df) - pred_trading_days) + pred_len = min(pred_trading_days, len(df) - lookback) + + # 确保参数在合理范围内 + lookback = max(100, min(lookback, 400)) + pred_len = max(20, min(pred_len, 120)) + + print(f"📊 参数计算:") + print(f" 目标预测天数: {target_days} 天(自然日)") + print(f" 预计交易日数量: {pred_trading_days} 天") + print(f" 回看期数 (lookback): {lookback}") + print(f" 预测期数 (pred_len): {pred_len}") + + return lookback, pred_len + + +def generate_trading_dates_only(last_date, pred_len): + """ + 🎯 修复版:只生成交易日,排除周末和法定节假日 + """ + # 2025年法定节假日安排(修正版) + holidays_2025 = [ + '2025-01-01', # 元旦 + '2025-01-27', '2025-01-28', '2025-01-29', '2025-01-30', '2025-01-31', '2025-02-01', '2025-02-02', # 春节 + '2025-04-04', '2025-04-05', '2025-04-06', # 清明 + '2025-05-01', '2025-05-02', '2025-05-03', # 劳动节 + '2025-06-08', '2025-06-09', '2025-06-10', # 端午 + '2025-10-01', '2025-10-02', '2025-10-03', '2025-10-04', '2025-10-05', '2025-10-06', '2025-10-07', # 国庆节 + ] + + holidays = [datetime.strptime(date, '%Y-%m-%d').date() for date in holidays_2025] + + trading_dates = [] + current_date = last_date + timedelta(days=1) + + while len(trading_dates) < pred_len: + # 排除周末和节假日 + if current_date.weekday() < 5 and current_date.date() not in holidays: + trading_dates.append(current_date) + current_date += timedelta(days=1) + + print(f"📅 生成的纯交易日: 共 {len(trading_dates)} 天") + if trading_dates: + print(f" 起始: {trading_dates[0].strftime('%Y-%m-%d')}") + print(f" 结束: {trading_dates[-1].strftime('%Y-%m-%d')}") + + return trading_dates + + +def calculate_optimal_interval(min_val, max_val): + """ + 计算最优的Y轴刻度间隔 + """ + range_val = max_val - min_val + if range_val <= 0: + return 1.0 + + if range_val < 1: + interval = 0.1 + elif range_val < 5: + interval = 0.5 + elif range_val < 10: + interval = 1.0 + elif range_val < 20: + interval = 2.0 + elif range_val < 50: + interval = 5.0 + elif range_val < 100: + interval = 10.0 + elif range_val < 200: + interval = 20.0 + elif range_val < 500: + interval = 50.0 + else: + interval = 100.0 + + return interval + + +# ==================== 增强版市场因素分析器 ==================== +class EnhancedMarketFactorAnalyzer: + """增强版市场因素分析器 - 整合更多维度的市场因素""" + + def __init__(self): + self.market_data = {} + self.sector_data = {} + self.macro_factors = {} + self.policy_factors = {} + + def analyze_market_trend(self, index_codes=["000001", "399001"]): + """ + 分析大盘趋势 - 多指数综合分析 + """ + try: + print(f"📊 综合分析大盘趋势...") + + market_analysis = {} + + for index_code in index_codes: + index_name = "上证指数" if index_code == "000001" else "深证成指" + print(f" 分析{index_name}({index_code})...") + + # 获取指数数据 + index_df = ak.stock_zh_index_hist(symbol=index_code, period="daily") + + if index_df is None or index_df.empty: + print(f" ❌ 无法获取{index_name}数据") + continue + + # 重命名列 + index_df = index_df.rename(columns={ + '日期': 'date', '收盘': 'close', '开盘': 'open', + '最高': 'high', '最低': 'low', '成交量': 'volume' + }) + index_df['date'] = pd.to_datetime(index_df['date']) + index_df = index_df.sort_values('date').reset_index(drop=True) + + # 计算技术指标 + index_df['ma5'] = index_df['close'].rolling(5).mean() + index_df['ma20'] = index_df['close'].rolling(20).mean() + index_df['ma60'] = index_df['close'].rolling(60).mean() + index_df['vol_ma5'] = index_df['volume'].rolling(5).mean() + + # 技术分析 + current_data = index_df.iloc[-1] + prev_data = index_df.iloc[-2] + + # 均线多头排列判断 + ma_condition = (current_data['ma5'] > current_data['ma20'] > current_data['ma60']) + + # 价格站在20日均线以上 + price_above_ma20 = current_data['close'] > current_data['ma20'] + + # 成交量配合 + volume_condition = current_data['volume'] > current_data['vol_ma5'] * 0.8 + + # 趋势强度 + trend_strength = self._calculate_trend_strength(index_df) + + is_main_uptrend = ma_condition and price_above_ma20 and trend_strength > 0.6 + + market_analysis[index_name] = { + 'is_main_uptrend': is_main_uptrend, + 'trend_strength': trend_strength, + 'current_close': current_data['close'], + 'price_change_pct': ((current_data['close'] - prev_data['close']) / prev_data['close']) * 100, + 'market_status': '主升浪' if is_main_uptrend else '震荡调整' + } + + # 综合判断 + if market_analysis: + avg_trend_strength = np.mean([data['trend_strength'] for data in market_analysis.values()]) + uptrend_count = sum(1 for data in market_analysis.values() if data['is_main_uptrend']) + overall_uptrend = uptrend_count >= len(market_analysis) * 0.5 + + final_analysis = { + 'overall_is_main_uptrend': overall_uptrend, + 'overall_trend_strength': avg_trend_strength, + 'detailed_analysis': market_analysis, + 'market_status': '主升浪' if overall_uptrend else '震荡调整' + } + + print(f"✅ 大盘分析完成: {final_analysis['market_status']}, 综合趋势强度: {avg_trend_strength:.2f}") + return final_analysis + + return self._get_default_market_analysis() + + except Exception as e: + print(f"❌ 大盘分析错误: {e}") + return self._get_default_market_analysis() + + def analyze_sector_resonance(self, stock_code): + """ + 分析板块共振效应 - 增强版行业分析 + """ + try: + print(f"🔄 分析板块共振效应...") + + # 获取股票所属行业和概念 + industry = "未知" + concepts = [] + + try: + stock_info = ak.stock_individual_info_em(symbol=stock_code) + if not stock_info.empty and 'value' in stock_info.columns: + industry_row = stock_info[stock_info['item'] == '行业'] + if not industry_row.empty: + industry = industry_row['value'].iloc[0] + except: + pass + + # 热门板块和概念映射 + hot_sectors = { + '机器人': {'momentum': 0.85, 'limit_up_stocks': 18, 'active': True, + 'description': '人形机器人、工业自动化'}, + '半导体': {'momentum': 0.8, 'limit_up_stocks': 15, 'active': True, 'description': '芯片国产替代'}, + '人工智能': {'momentum': 0.75, 'limit_up_stocks': 12, 'active': True, 'description': 'AI大模型、算力'}, + '低空经济': {'momentum': 0.7, 'limit_up_stocks': 10, 'active': True, 'description': '无人机、eVTOL'}, + '新能源': {'momentum': 0.6, 'limit_up_stocks': 8, 'active': True, 'description': '光伏、储能'}, + '医药': {'momentum': 0.5, 'limit_up_stocks': 5, 'active': False, 'description': '创新药'} + } + + # 判断当前股票所属热门板块 + matched_sectors = [] + for sector, data in hot_sectors.items(): + if (sector in industry or + (stock_code == '600580' and sector in ['机器人', '低空经济']) or # 卧龙电驱特殊处理 + (stock_code == '300207' and sector in ['新能源'])): + matched_sectors.append({ + 'sector': sector, + 'momentum': data['momentum'], + 'limit_up_stocks': data['limit_up_stocks'], + 'is_active': data['active'], + 'description': data['description'] + }) + + # 计算综合共振分数 + if matched_sectors: + resonance_score = np.mean([sector['momentum'] for sector in matched_sectors]) + is_sector_hot = any(sector['is_active'] for sector in matched_sectors) + main_sector = max(matched_sectors, key=lambda x: x['momentum']) + else: + resonance_score = 0.5 + is_sector_hot = False + main_sector = {'sector': '传统行业', 'momentum': 0.5, 'description': '无热门概念'} + + analysis = { + 'industry': industry, + 'matched_sectors': matched_sectors, + 'main_sector': main_sector, + 'is_sector_hot': is_sector_hot, + 'resonance_score': resonance_score, + 'sector_count': len(matched_sectors) + } + + print(f"✅ 板块分析完成: {industry}, 匹配{len(matched_sectors)}个热门板块, 共振分数: {resonance_score:.2f}") + return analysis + + except Exception as e: + print(f"❌ 板块分析错误: {e}") + return self._get_default_sector_analysis() + + def analyze_macro_factors(self): + """ + 分析宏观因素 - 结合国内外政策 + """ + try: + print(f"🌍 分析宏观因素...") + + # 美国降息周期分析 - 基于最新信息 + us_rate_analysis = { + 'current_rate': 4.25, # 联邦基金利率目标区间4.00%-4.25% + 'trend': '降息周期', + 'recent_cut': '2025年9月降息25个基点', + 'expected_cuts_2025': 2, # 市场预期2025年还有两次降息 + 'expected_cuts_2026': 2, + 'impact_on_emerging_markets': 'positive', + 'usd_index_support': 95.0, # 美元指数短期支撑位 + 'analysis': '美联储开启宽松周期,利好全球流动性' + } + + # 国内政策因素 - 基于最新政策 + domestic_policy = { + 'monetary_policy': '稳健偏松', + 'fiscal_policy': '积极财政', + 'market_liquidity': '合理充裕', + 'industrial_policy': '设备更新、以旧换新', # 大规模设备更新政策 + 'employment_policy': '稳就业政策加力', # 国务院稳就业政策 + 'analysis': '政策组合拳发力,经济稳中向好' + } + + # 行业政策支持 + industry_policy = { + 'robot_policy': '机器人产业政策支持', + 'chip_policy': '国产替代加速推进', + 'AI_policy': '人工智能发展规划', + 'low_altitude': '低空经济发展规划' + } + + macro_analysis = { + 'us_rate_cycle': us_rate_analysis, + 'domestic_policy': domestic_policy, + 'industry_policy': industry_policy, + 'global_liquidity_outlook': '改善', + 'overall_macro_score': 0.75 # 宏观环境整体偏积极 + } + + print( + f"✅ 宏观分析完成: 美国{us_rate_analysis['trend']}, 国内政策积极, 宏观评分: {macro_analysis['overall_macro_score']:.2f}") + return macro_analysis + + except Exception as e: + print(f"❌ 宏观分析错误: {e}") + return self._get_default_macro_analysis() + + def analyze_company_fundamentals(self, stock_code): + """ + 分析公司基本面 - 针对特定股票 + """ + try: + print(f"🏢 分析公司基本面...") + + # 卧龙电驱特殊分析 + if stock_code == '600580': + fundamentals = { + 'company_name': '卧龙电驱', + 'business_areas': ['工业电机', '机器人关键部件', '航空电机', '新能源汽车驱动'], + 'recent_developments': [ + '与智元机器人实现双向持股,推进具身智能机器人技术研发', + '成立浙江龙飞电驱,专注航空电机业务', + '发布AI外骨骼机器人及灵巧手', + '布局高爆发关节模组、伺服驱动器等人形机器人关键部件' + ], + 'growth_drivers': [ + '设备更新政策推动工业电机需求', + '机器人产业快速发展', + '低空经济政策支持', + '出海战略加速' + ], + 'risk_factors': [ + '机器人业务营收占比仅2.71%,占比较低', + '工业需求景气度波动', + '原料价格波动风险' + ], + 'investment_rating': '积极关注', + 'fundamental_score': 0.7 + } + else: + # 其他股票的基础分析 + fundamentals = { + 'company_name': '未知', + 'business_areas': [], + 'recent_developments': [], + 'growth_drivers': [], + 'risk_factors': [], + 'investment_rating': '中性', + 'fundamental_score': 0.5 + } + + print(f"✅ 基本面分析完成: {fundamentals['company_name']}, 评分: {fundamentals['fundamental_score']:.2f}") + return fundamentals + + except Exception as e: + print(f"❌ 基本面分析错误: {e}") + return self._get_default_fundamental_analysis() + + def _calculate_trend_strength(self, df): + """计算趋势强度""" + if len(df) < 20: + return 0.5 + + ma_slope = (df['ma5'].iloc[-1] - df['ma5'].iloc[-20]) / df['ma5'].iloc[-20] + price_slope = (df['close'].iloc[-1] - df['close'].iloc[-20]) / df['close'].iloc[-20] + + volume_trend = df['volume'].iloc[-5:].mean() / df['volume'].iloc[-10:-5].mean() + + strength = (ma_slope * 0.4 + price_slope * 0.4 + min(volume_trend - 1, 0.2) * 0.2) + return max(0, min(1, strength * 10)) + + def _get_default_market_analysis(self): + return { + 'overall_is_main_uptrend': False, + 'overall_trend_strength': 0.5, + 'market_status': '未知', + 'detailed_analysis': {} + } + + def _get_default_sector_analysis(self): + return { + 'industry': '未知', + 'matched_sectors': [], + 'main_sector': {'sector': '未知', 'momentum': 0.5, 'description': ''}, + 'is_sector_hot': False, + 'resonance_score': 0.5, + 'sector_count': 0 + } + + def _get_default_macro_analysis(self): + return { + 'us_rate_cycle': {'trend': '未知', 'expected_cuts_2025': 0}, + 'domestic_policy': {'monetary_policy': '中性'}, + 'overall_macro_score': 0.5 + } + + def _get_default_fundamental_analysis(self): + return { + 'company_name': '未知', + 'business_areas': [], + 'recent_developments': [], + 'growth_drivers': [], + 'risk_factors': [], + 'investment_rating': '中性', + 'fundamental_score': 0.5 + } + + +# ==================== 优化的预测平滑函数 ==================== +def smooth_prediction_results(prediction_df, historical_df, smooth_factor=0.3): + """ + 🎯 优化预测结果的平滑处理,避免剧烈波动 + """ + print("🔄 应用预测结果平滑处理...") + + smoothed_df = prediction_df.copy() + + # 获取历史数据的趋势 + recent_trend = calculate_recent_trend(historical_df) + + # 对价格序列进行平滑 + price_columns = ['close', 'open', 'high', 'low'] + for col in price_columns: + if col in smoothed_df.columns: + original_values = smoothed_df[col].values + + # 应用移动平均平滑 + window_size = max(3, min(7, len(original_values) // 5)) + smoothed_values = pd.Series(original_values).rolling( + window=window_size, center=True, min_periods=1 + ).mean() + + # 结合历史趋势进行微调 + trend_adjusted = smoothed_values * (1 + recent_trend * smooth_factor) + + smoothed_df[col] = trend_adjusted.values + + # 对成交量进行合理调整 + if 'volume' in smoothed_df.columns: + hist_volume_mean = historical_df['volume'].tail(20).mean() + current_volume = smoothed_df['volume'].values + + # 保持成交量在合理范围内 + volume_factor = 0.8 + 0.4 * np.random.random(len(current_volume)) + adjusted_volume = current_volume * volume_factor + + # 确保成交量不会异常波动 + volume_std = historical_df['volume'].tail(50).std() + volume_min = hist_volume_mean * 0.3 + volume_max = hist_volume_mean * 3.0 + + smoothed_df['volume'] = np.clip(adjusted_volume, volume_min, volume_max) + + print("✅ 预测结果平滑完成") + return smoothed_df + + +def calculate_recent_trend(historical_df, lookback_days=20): + """ + 计算近期价格趋势 + """ + if len(historical_df) < lookback_days: + lookback_days = len(historical_df) + + recent_prices = historical_df['close'].tail(lookback_days).values + if len(recent_prices) < 2: + return 0 + + # 计算线性回归斜率作为趋势 + x = np.arange(len(recent_prices)) + slope = np.polyfit(x, recent_prices, 1)[0] + + # 归一化为趋势强度 (-1 到 1) + price_range = np.ptp(recent_prices) + if price_range > 0: + trend_strength = slope / price_range * len(recent_prices) + else: + trend_strength = 0 + + return np.clip(trend_strength, -0.1, 0.1) # 限制趋势强度 + + +def apply_post_holiday_adjustment(prediction_df, future_dates, holiday_periods): + """ + 🎯 修复版:应用节后调整,避免国庆后异常下跌 + """ + print("🔄 应用节后日历效应调整...") + + adjusted_df = prediction_df.copy() + + for holiday in holiday_periods: + holiday_start = pd.Timestamp(holiday['start']) + holiday_end = pd.Timestamp(holiday['end']) + adjustment_days = holiday['adjustment_days'] + effect_strength = holiday['effect_strength'] + + # 计算调整期结束日期 + adjustment_end = holiday_end + timedelta(days=adjustment_days) + + # 找到在节后调整期内的日期索引 + post_holiday_indices = [] + for i, date in enumerate(future_dates): + if holiday_end <= date < adjustment_end: + post_holiday_indices.append(i) + + # 应用节后效应调整 + if post_holiday_indices: + for col in ['close', 'open', 'high', 'low']: + if col in adjusted_df.columns: + for idx in post_holiday_indices: + adjusted_df.iloc[idx][col] = adjusted_df.iloc[idx][col] * (1 + effect_strength) + + print("✅ 节后调整完成") + return adjusted_df + + +# ==================== 价格合理性检查函数 ==================== +def validate_prediction_results(historical_df, prediction_df, max_price_change=0.3): + """ + 🎯 验证预测结果的合理性,避免异常价格波动 + """ + print("🔍 验证预测结果合理性...") + + validated_df = prediction_df.copy() + current_price = historical_df['close'].iloc[-1] + + # 检查价格列的合理性 + price_columns = ['close', 'open', 'high', 'low'] + + for col in price_columns: + if col in validated_df.columns: + # 计算最大允许的价格变化范围 + max_allowed_change = current_price * max_price_change + + # 检查每个预测价格 + for i in range(len(validated_df)): + predicted_price = validated_df[col].iloc[i] + + # 如果预测价格超出合理范围,进行修正 + if abs(predicted_price - current_price) > max_allowed_change: + # 基于历史波动率进行修正 + correction_factor = 0.8 + 0.4 * np.random.random() + corrected_price = current_price * (1 + (predicted_price / current_price - 1) * correction_factor) + validated_df.iloc[i][col] = corrected_price + + print(f"⚠️ 修正异常{col}价格: {predicted_price:.2f} -> {corrected_price:.2f}") + + print("✅ 预测结果验证完成") + return validated_df + + +# ==================== GUI版本预测函数 ==================== +def run_comprehensive_prediction_gui(stock_code, stock_name, data_dir, pred_days, output_dir, history_years=1, + progress_callback=None, result_callback=None): + """ + GUI版本的预测函数 + """ + + def update_progress(message): + if progress_callback: + progress_callback(message) + print(message) + + def update_result(message): + if result_callback: + result_callback(message) + print(message) + + try: + # 初始化市场分析器 + market_analyzer = EnhancedMarketFactorAnalyzer() + + update_progress(f"🎯 开始 {stock_name}({stock_code}) 预测流程") + update_progress("=" * 50) + + # 1. 获取数据 + update_progress("\n步骤1: 获取股票数据...") + success, csv_file_path = get_stock_data(stock_code, data_dir) + if not success: + update_result("❌ 无法获取股票数据,预测终止") + return False, "无法获取股票数据" + + # 2. 加载模型和分词器 + update_progress("\n步骤2: 加载Kronos模型和分词器...") + try: + tokenizer = KronosTokenizer.from_pretrained("NeoQuasar/Kronos-Tokenizer-base") + model = Kronos.from_pretrained("NeoQuasar/Kronos-base") + update_progress("✅ 模型加载完成 - 使用Kronos-base模型") + except Exception as e: + error_msg = f"❌ 模型加载失败: {e}" + update_result(error_msg) + update_progress("⚠️ 预测功能不可用,请检查模型安装") + return False, error_msg + + # 3. 实例化预测器 + update_progress("步骤3: 初始化预测器...") + predictor = KronosPredictor(model, tokenizer, device="cuda:0", max_context=512) + update_progress("✅ 预测器初始化完成") + + # 4. 准备数据 + update_progress("步骤4: 准备股票数据...") + df = prepare_stock_data(csv_file_path, stock_code, history_years) + + # 5. 计算预测参数 + update_progress("步骤5: 计算预测参数...") + lookback, pred_len = calculate_prediction_parameters(df, target_days=pred_days) + + if pred_len <= 0: + update_result("❌ 数据量不足,无法进行预测") + return False, "数据量不足" + + update_progress(f"✅ 最终参数 - 回看期: {lookback}, 预测期: {pred_len}") + + # 6. 准备输入数据 + update_progress("步骤6: 准备输入数据...") + x_df = df.loc[-lookback:, ['open', 'high', 'low', 'close', 'volume', 'amount']].reset_index(drop=True) + x_timestamp = df.loc[-lookback:, 'timestamps'].reset_index(drop=True) + + # 生成未来日期 - 🎯 修复:只生成交易日 + last_historical_date = df['timestamps'].iloc[-1] + future_dates = generate_trading_dates_only(last_historical_date, pred_len) + + if len(future_dates) < pred_len: + update_progress(f"⚠️ 警告:只生成了 {len(future_dates)} 个交易日,少于请求的 {pred_len} 天") + pred_len = len(future_dates) + + update_progress(f"输入数据形状: {x_df.shape}") + update_progress(f"历史数据时间范围: {x_timestamp.iloc[0]} 到 {x_timestamp.iloc[-1]}") + if future_dates: + update_progress(f"预测时间范围: {future_dates[0]} 到 {future_dates[-1]}") + + # 7. 执行基础预测 + update_progress("步骤7: 执行基础价格预测...") + pred_df = predictor.predict( + df=x_df, + x_timestamp=x_timestamp, + y_timestamp=pd.Series(future_dates), + pred_len=pred_len, + T=1.0, + top_p=0.9, + sample_count=1, + verbose=True + ) + + update_progress("✅ 基础预测完成") + + # 🎯 新增:对基础预测进行合理性检查 + update_progress("步骤7.2: 验证预测结果合理性...") + historical_df_for_validation = df.loc[-lookback:].reset_index(drop=True) + validated_pred_df = validate_prediction_results(historical_df_for_validation, pred_df) + + # 🎯 新增:对基础预测进行平滑处理 + update_progress("步骤7.5: 对预测结果进行平滑优化...") + smoothed_pred_df = smooth_prediction_results(validated_pred_df, historical_df_for_validation) + + # 🎯 修复:应用节后调整(特别是国庆节后) + holiday_periods = [ + { + 'start': '2025-10-01', + 'end': '2025-10-09', # 国庆后第一个交易日(10月9日周四) + 'adjustment_days': 5, + 'effect_strength': 0.03 # 节后通常有正面效应 + } + ] + + adjusted_pred_df = apply_post_holiday_adjustment(smoothed_pred_df, future_dates, holiday_periods) + + # 8. 使用多维度市场因素增强预测 + update_progress("步骤8: 应用多维度市场因素增强预测...") + enhanced_pred_df, enhancement_info = enhance_prediction_with_market_factors( + df.loc[-lookback:].reset_index(drop=True), + adjusted_pred_df, # 使用平滑调整后的预测结果 + stock_code, + market_analyzer + ) + + # 将增强预测结果添加到信息中 + enhancement_info['enhanced_prediction'] = enhanced_pred_df + + # 9. 创建综合市场分析报告 + update_progress("步骤9: 创建市场分析报告...") + market_report = create_comprehensive_market_report(enhancement_info, output_dir, stock_code) + + # 10. 生成预测图表 + update_progress("步骤10: 生成预测图表...") + historical_df = df.loc[-lookback:].reset_index(drop=True) + chart_path = plot_optimized_prediction_gui( + historical_df, adjusted_pred_df, enhanced_pred_df, future_dates, + stock_code, stock_name, output_dir, enhancement_info + ) + + # 11. 生成预测报告 + update_progress("步骤11: 生成预测报告...") + if len(enhanced_pred_df) > 0: + current_price = historical_df['close'].iloc[-1] + base_predicted_price = adjusted_pred_df['close'].iloc[-1] if len(adjusted_pred_df) > 0 else current_price + enhanced_predicted_price = enhanced_pred_df['close'].iloc[-1] + + base_change_pct = (base_predicted_price / current_price - 1) * 100 + enhanced_change_pct = (enhanced_predicted_price / current_price - 1) * 100 + + # 输出预测结果 + update_result(f"\n📈 {stock_name}({stock_code}) 预测报告") + update_result("=" * 50) + update_result(f"当前价格: {current_price:.2f} 元") + update_result(f"平滑预测价格: {base_predicted_price:.2f} 元 ({base_change_pct:+.2f}%)") + update_result(f"增强预测价格: {enhanced_predicted_price:.2f} 元 ({enhanced_change_pct:+.2f}%)") + update_result(f"市场因素调整因子: {enhancement_info['adjustment_factor']:.4f}") + update_result(f"大盘状态: {enhancement_info['market_analysis']['market_status']}") + update_result(f"板块共振: {enhancement_info['sector_analysis']['main_sector']['sector']}") + update_result(f"宏观环境: 美国{enhancement_info['macro_analysis']['us_rate_cycle']['trend']}") + update_result(f"公司评级: {enhancement_info['fundamental_analysis']['investment_rating']}") + + # 保存详细预测数据 + prediction_details = pd.DataFrame({ + '日期': future_dates, + '平滑预测收盘价': adjusted_pred_df['close'].values if len( + adjusted_pred_df) > 0 else [current_price] * len(future_dates), + '增强预测收盘价': enhanced_pred_df['close'].values, + '预测成交量': enhanced_pred_df['volume'].values + }) + + prediction_file = os.path.join(output_dir, f'{stock_code}_comprehensive_predictions.csv') + prediction_details.to_csv(prediction_file, index=False, encoding='utf-8-sig') + update_progress(f"💾 详细预测数据已保存: {prediction_file}") + + update_progress(f"\n🎉 {stock_name}({stock_code}) 预测完成!") + update_progress(f"📊 预测图表: {chart_path}") + + return True, "预测完成" + + except Exception as e: + error_msg = f"❌ 预测过程中出现错误: {e}" + update_result(error_msg) + import traceback + traceback.print_exc() + return False, error_msg + + +def enhance_prediction_with_market_factors(historical_df, prediction_df, stock_code, market_analyzer): + """ + 使用市场因素增强预测结果 + """ + print("\n🎯 使用市场因素增强预测...") + + # 获取各类市场分析 + market_analysis = market_analyzer.analyze_market_trend() + sector_analysis = market_analyzer.analyze_sector_resonance(stock_code) + macro_analysis = market_analyzer.analyze_macro_factors() + fundamental_analysis = market_analyzer.analyze_company_fundamentals(stock_code) + + # 计算综合调整因子 + adjustment_factor = calculate_enhanced_adjustment_factor( + market_analysis, sector_analysis, macro_analysis, fundamental_analysis + ) + + print(f"📈 综合调整因子: {adjustment_factor:.4f}") + + # 应用调整到预测结果 + enhanced_prediction = prediction_df.copy() + + # 对价格预测进行调整 + price_columns = ['close', 'open', 'high', 'low'] + for col in price_columns: + if col in enhanced_prediction.columns: + enhanced_prediction[col] = enhanced_prediction[col] * adjustment_factor + + # 对成交量进行调整 + if 'volume' in enhanced_prediction.columns: + volume_adjustment = 1 + (adjustment_factor - 1) * 0.3 + enhanced_prediction['volume'] = enhanced_prediction['volume'] * volume_adjustment + + return enhanced_prediction, { + 'market_analysis': market_analysis, + 'sector_analysis': sector_analysis, + 'macro_analysis': macro_analysis, + 'fundamental_analysis': fundamental_analysis, + 'adjustment_factor': adjustment_factor + } + + +def calculate_enhanced_adjustment_factor(market_analysis, sector_analysis, macro_analysis, fundamental_analysis): + """ + 计算基于多维度市场因素的调整因子 + """ + base_factor = 1.0 + + # 1. 大盘趋势影响 (权重25%) + if market_analysis['overall_is_main_uptrend']: + trend_strength = market_analysis['overall_trend_strength'] + base_factor *= (1 + trend_strength * 0.08) + else: + trend_strength = market_analysis['overall_trend_strength'] + base_factor *= (1 + (trend_strength - 0.5) * 0.04) + + # 2. 板块共振影响 (权重25%) + resonance_score = sector_analysis['resonance_score'] + sector_count = sector_analysis['sector_count'] + + if sector_analysis['is_sector_hot']: + base_factor *= (1 + resonance_score * 0.06 + min(sector_count * 0.01, 0.03)) + else: + base_factor *= (1 + (resonance_score - 0.5) * 0.02) + + # 3. 宏观因素影响 (权重20%) + macro_score = macro_analysis['overall_macro_score'] + base_factor *= (1 + (macro_score - 0.5) * 0.06) + + # 4. 美国降息周期特殊影响 (权重10%) + us_rate_trend = macro_analysis['us_rate_cycle']['trend'] + if us_rate_trend == '降息周期': + expected_cuts = macro_analysis['us_rate_cycle']['expected_cuts_2025'] + base_factor *= (1 + expected_cuts * 0.015) + + # 5. 公司基本面影响 (权重20%) + fundamental_score = fundamental_analysis['fundamental_score'] + base_factor *= (1 + (fundamental_score - 0.5) * 0.08) + + # 🎯 限制调整幅度在更合理范围内 (0.9 ~ 1.1),避免过度调整 + return max(0.9, min(1.1, base_factor)) + + +def create_comprehensive_market_report(enhancement_info, output_dir, stock_code): + """ + 创建综合市场分析报告 + """ + report = { + 'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S'), + 'stock_code': stock_code, + 'market_analysis': enhancement_info['market_analysis'], + 'sector_analysis': enhancement_info['sector_analysis'], + 'macro_analysis': enhancement_info['macro_analysis'], + 'fundamental_analysis': enhancement_info['fundamental_analysis'], + 'adjustment_factor': enhancement_info['adjustment_factor'] + } + + # 保存报告 + report_file = os.path.join(output_dir, f'{stock_code}_comprehensive_analysis_report.json') + with open(report_file, 'w', encoding='utf-8') as f: + json.dump(report, f, ensure_ascii=False, indent=2) + + print(f"📋 综合分析报告已保存: {report_file}") + return report + + +def plot_optimized_prediction_gui(historical_df, base_pred_df, enhanced_pred_df, future_trading_dates, + stock_code, stock_name, output_dir, enhancement_info=None): + """ + 🎯 优化版:清晰显示每个交易日的预测图表 + """ + ensure_output_directory(output_dir) + + # 设置配色 + colors = { + 'historical': '#1f77b4', + 'prediction': '#ff7f0e', + 'enhanced': '#2ca02c', + 'background': '#f8f9fa', + 'grid': '#e9ecef' + } + + # 创建图表 + fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2, figsize=(16, 12)) + fig.suptitle(f'{stock_name}({stock_code}) - 优化版交易日预测图表', fontsize=16, fontweight='bold') + + # 设置背景色 + fig.patch.set_facecolor('white') + for ax in [ax1, ax2, ax3, ax4]: + ax.set_facecolor(colors['background']) + + # 🎯 优化1: 使用实际日期作为x轴,但只显示交易日 + all_dates = list(historical_df['timestamps']) + future_trading_dates + + # 1. 主价格图表 + current_price = historical_df['close'].iloc[-1] + + # 绘制历史价格 + ax1.plot(historical_df['timestamps'], historical_df['close'], + color=colors['historical'], linewidth=2.5, label='历史价格') + + # 绘制预测价格 + if len(future_trading_dates) > 0: + # 绘制基础预测 + ax1.plot(future_trading_dates, base_pred_df['close'], + color=colors['prediction'], linewidth=2, label='平滑预测', linestyle='--') + + # 绘制增强预测 + ax1.plot(future_trading_dates, enhanced_pred_df['close'], + color=colors['enhanced'], linewidth=2.5, label='增强预测') + + # 🎯 修复:使用更安全的关键日期标记 + mark_key_dates_safe(ax1, future_trading_dates, enhanced_pred_df) + + ax1.set_ylabel('收盘价 (元)', fontsize=12, fontweight='bold') + ax1.legend(loc='upper left', fontsize=10) + ax1.grid(True, color=colors['grid'], alpha=0.7) + ax1.set_title(f'价格走势预测 - 当前价: {current_price:.2f}元', fontweight='bold', fontsize=13) + + # 🎯 优化2: 使用每周标记,避免过于密集 + ax1.xaxis.set_major_formatter(mdates.DateFormatter('%m-%d')) + ax1.xaxis.set_major_locator(mdates.WeekdayLocator(byweekday=mdates.MO, interval=2)) # 每两周一个标记 + plt.setp(ax1.xaxis.get_majorticklabels(), rotation=45, fontsize=9) + + # 2. 成交量图表 + ax2.bar(historical_df['timestamps'], historical_df['volume'], + alpha=0.6, color=colors['historical'], label='历史成交量') + + if len(future_trading_dates) > 0: + ax2.bar(future_trading_dates, enhanced_pred_df['volume'], + alpha=0.6, color=colors['enhanced'], label='预测成交量') + + ax2.set_ylabel('成交量', fontsize=12, fontweight='bold') + ax2.legend(loc='upper left', fontsize=10) + ax2.grid(True, color=colors['grid'], alpha=0.7) + ax2.set_title('成交量预测', fontweight='bold', fontsize=13) + ax2.xaxis.set_major_formatter(mdates.DateFormatter('%m-%d')) + ax2.xaxis.set_major_locator(mdates.WeekdayLocator(byweekday=mdates.MO, interval=2)) + plt.setp(ax2.xaxis.get_majorticklabels(), rotation=45, fontsize=9) + + # 3. 价格变化率图表 + ax3.plot(historical_df['timestamps'], historical_df['close'].pct_change() * 100, + color=colors['historical'], linewidth=1.5, label='历史涨跌幅', alpha=0.7) + + if len(future_trading_dates) > 0: + pred_returns = enhanced_pred_df['close'].pct_change() * 100 + ax3.plot(future_trading_dates, pred_returns, + color=colors['enhanced'], linewidth=2, label='预测涨跌幅') + + # 添加零线参考 + ax3.axhline(y=0, color='red', linestyle='-', alpha=0.3, linewidth=1) + + ax3.set_ylabel('日涨跌幅 (%)', fontsize=12, fontweight='bold') + ax3.legend(loc='upper left', fontsize=10) + ax3.grid(True, color=colors['grid'], alpha=0.7) + ax3.set_title('价格变化率分析', fontweight='bold', fontsize=13) + ax3.xaxis.set_major_formatter(mdates.DateFormatter('%m-%d')) + ax3.xaxis.set_major_locator(mdates.WeekdayLocator(byweekday=mdates.MO, interval=2)) + plt.setp(ax3.xaxis.get_majorticklabels(), rotation=45, fontsize=9) + + # 4. 市场因素分析 + if enhancement_info: + factors = ['大盘趋势', '板块共振', '宏观环境', '美国降息', '基本面'] + scores = [ + enhancement_info['market_analysis']['overall_trend_strength'], + enhancement_info['sector_analysis']['resonance_score'], + enhancement_info['macro_analysis']['overall_macro_score'], + 0.7 if enhancement_info['macro_analysis']['us_rate_cycle']['trend'] == '降息周期' else 0.3, + enhancement_info['fundamental_analysis']['fundamental_score'] + ] + + colors_bars = [colors['historical'], colors['prediction'], colors['enhanced'], '#f39c12', '#9b59b6'] + + bars = ax4.bar(factors, scores, color=colors_bars, alpha=0.8, edgecolor='black', linewidth=1) + ax4.set_ylim(0, 1) + ax4.set_ylabel('评分', fontsize=12, fontweight='bold') + ax4.set_title('市场因素评分分析', fontweight='bold', fontsize=13) + ax4.grid(True, alpha=0.3, axis='y') + + # 在柱状图上显示具体数值 + for i, (bar, score) in enumerate(zip(bars, scores)): + height = bar.get_height() + ax4.text(bar.get_x() + bar.get_width() / 2., height + 0.02, + f'{score:.2f}', ha='center', va='bottom', fontsize=10, fontweight='bold') + + # 添加平均线 + avg_score = np.mean(scores) + ax4.axhline(y=avg_score, color='red', linestyle='--', alpha=0.7, + label=f'平均分: {avg_score:.2f}') + ax4.legend(loc='upper right', fontsize=9) + + plt.tight_layout() + + # 保存图片 + chart_filename = os.path.join(output_dir, f'{stock_code}_optimized_prediction.png') + plt.savefig(chart_filename, dpi=300, bbox_inches='tight', facecolor='white') + plt.close() + + print(f"📊 优化版预测图表已保存: {chart_filename}") + return chart_filename + + +def mark_key_dates_safe(ax, future_dates, pred_df): + """ + 🎯 安全版:标记关键日期和价格点,避免类型错误 + """ + if len(future_dates) == 0 or len(pred_df) == 0: + return + + try: + # 重置索引确保使用整数索引 + pred_df_reset = pred_df.reset_index(drop=True) + + # 获取最高点和最低点的整数索引 + if hasattr(pred_df_reset['close'], 'idxmax'): + max_idx = pred_df_reset['close'].idxmax() + min_idx = pred_df_reset['close'].idxmin() + else: + # 备用方法 + max_idx = np.argmax(pred_df_reset['close'].values) + min_idx = np.argmin(pred_df_reset['close'].values) + + # 确保索引在有效范围内 + max_idx = min(int(max_idx), len(future_dates) - 1) + min_idx = min(int(min_idx), len(future_dates) - 1) + + # 标记最高点 + if 0 <= max_idx < len(future_dates): + max_price = pred_df_reset['close'].iloc[max_idx] + ax.plot(future_dates[max_idx], max_price, + 'v', color='red', markersize=8, label=f'最高点: {max_price:.2f}') + + # 标记最低点 + if 0 <= min_idx < len(future_dates): + min_price = pred_df_reset['close'].iloc[min_idx] + ax.plot(future_dates[min_idx], min_price, + '^', color='green', markersize=8, label=f'最低点: {min_price:.2f}') + + # 标记预测结束点 + if len(future_dates) > 0: + final_price = pred_df_reset['close'].iloc[-1] + ax.plot(future_dates[-1], final_price, + 's', color='blue', markersize=6, label=f'最终预测: {final_price:.2f}') + + except Exception as e: + print(f"⚠️ 标记关键日期时出现错误: {e}") + # 如果出错,跳过标记但不影响整体流程 + + +# ==================== 主函数 ==================== +def main(): + """主函数:启动GUI界面""" + root = tk.Tk() + app = StockPredictorGUI(root) + root.mainloop() + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/examples/run_backtest_kronos.py b/examples/run_backtest_kronos.py new file mode 100644 index 0000000..2e34157 --- /dev/null +++ b/examples/run_backtest_kronos.py @@ -0,0 +1,455 @@ +# run_backtest.py +import pandas as pd +import numpy as np +import matplotlib.pyplot as plt +import os +from datetime import datetime, timedelta +import warnings + +warnings.filterwarnings('ignore') + +# 设置中文字体 +plt.rcParams['font.sans-serif'] = ['SimHei'] +plt.rcParams['axes.unicode_minus'] = False + + +class KronosBacktester: + """ + Kronos模型回测类 + """ + + def __init__(self, data_dir, model_dir, initial_capital=100000): + """ + 初始化回测器 + + 参数: + data_dir: 数据目录 + model_dir: 模型预测结果目录 + initial_capital: 初始资金 + """ + self.data_dir = data_dir + self.model_dir = model_dir + self.initial_capital = initial_capital + self.results = {} + + def load_historical_data(self, stock_code): + """ + 加载历史数据 + """ + csv_file = os.path.join(self.data_dir, f"{stock_code}_stock_data.csv") + if not os.path.exists(csv_file): + raise FileNotFoundError(f"数据文件不存在: {csv_file}") + + df = pd.read_csv(csv_file, encoding='utf-8-sig') + + # 检查列名并标准化 + column_mapping = { + '日期': 'date', + '开盘价': 'open', + '最高价': 'high', + '最低价': 'low', + '收盘价': 'close', + '成交量': 'volume', + '成交额': 'amount' + } + + # 重命名列 + for old_col, new_col in column_mapping.items(): + if old_col in df.columns: + df = df.rename(columns={old_col: new_col}) + + df['date'] = pd.to_datetime(df['date']) + df.set_index('date', inplace=True) + df = df.sort_index() + + print(f"✅ 加载历史数据: {len(df)} 条记录") + print(f"时间范围: {df.index.min()} 到 {df.index.max()}") + + return df + + def load_predictions(self, stock_code): + """ + 加载模型预测结果 + """ + # 尝试不同的预测文件命名 + pred_files = [ + os.path.join(self.model_dir, f"{stock_code}_kronos_predictions.csv"), + os.path.join(self.model_dir, f"{stock_code}_detailed_predictions.csv"), + os.path.join(self.model_dir, f"{stock_code}_predictions.csv") + ] + + pred_df = None + for pred_file in pred_files: + if os.path.exists(pred_file): + pred_df = pd.read_csv(pred_file, encoding='utf-8-sig') + print(f"✅ 找到预测文件: {pred_file}") + break + + if pred_df is None: + raise FileNotFoundError(f"未找到预测文件,请检查目录: {self.model_dir}") + + # 标准化列名 + column_mapping = { + '日期': 'date', + '预测收盘价': 'predicted_close', + '收盘价': 'predicted_close', + '预测成交量': 'predicted_volume', + '成交量': 'predicted_volume' + } + + for old_col, new_col in column_mapping.items(): + if old_col in pred_df.columns: + pred_df = pred_df.rename(columns={old_col: new_col}) + + pred_df['date'] = pd.to_datetime(pred_df['date']) + pred_df.set_index('date', inplace=True) + pred_df = pred_df.sort_index() + + print(f"✅ 加载预测数据: {len(pred_df)} 条记录") + print(f"预测时间范围: {pred_df.index.min()} 到 {pred_df.index.max()}") + + return pred_df + + def align_data(self, hist_df, pred_df): + """ + 对齐历史数据和预测数据的时间范围 + """ + # 找到历史数据的最后日期 + last_hist_date = hist_df.index.max() + + # 筛选预测数据,从历史数据结束后开始 + pred_df_aligned = pred_df[pred_df.index > last_hist_date] + + if len(pred_df_aligned) == 0: + # 如果没有未来的预测数据,使用所有预测数据 + pred_df_aligned = pred_df.copy() + print("⚠️ 警告:预测数据没有未来的日期,使用所有预测数据") + + print(f"✅ 数据对齐: 历史数据结束于 {last_hist_date}, 预测数据从 {pred_df_aligned.index.min()} 开始") + + return pred_df_aligned + + def calculate_trading_signals(self, hist_df, pred_df, threshold=0.02): + """ + 计算交易信号 + """ + # 对齐数据 + pred_df = self.align_data(hist_df, pred_df) + + # 合并历史数据和预测数据 + combined = pd.concat([ + hist_df[['close']].rename(columns={'close': 'actual'}), + pred_df[['predicted_close']].rename(columns={'predicted_close': 'predicted'}) + ], axis=1) + + # 计算预测收益率 + combined['pred_return'] = combined['predicted'].pct_change() + + # 生成交易信号 + combined['signal'] = 0 + combined['signal'] = np.where(combined['pred_return'] > threshold, 1, # 买入信号 + np.where(combined['pred_return'] < -threshold, -1, 0)) # 卖出信号 + + # 过滤信号:避免频繁交易 + combined['position'] = combined['signal'].replace(to_replace=0, method='ffill').fillna(0) + + return combined + + def run_backtest(self, combined_df): + """ + 运行回测 + """ + # 初始化资金和持仓 + capital = self.initial_capital + position = 0 + trades = [] + + # 回测记录 + backtest_results = pd.DataFrame(index=combined_df.index) + backtest_results['capital'] = capital + backtest_results['position'] = 0 + backtest_results['returns'] = 0.0 + backtest_results['price'] = combined_df['actual'].combine_first(combined_df['predicted']) + + for i, (date, row) in enumerate(combined_df.iterrows()): + current_price = row['actual'] if not pd.isna(row['actual']) else row['predicted'] + signal = row['position'] + + # 跳过无效价格 + if pd.isna(current_price): + continue + + # 执行交易 + if i > 0: # 从第二天开始 + prev_position = backtest_results['position'].iloc[i - 1] if i > 0 else 0 + + # 平仓信号 + if prev_position != 0 and signal == 0: + # 平仓 + capital = position * current_price + position = 0 + trades.append({ + 'date': date, + 'action': 'SELL', + 'price': current_price, + 'shares': prev_position, + 'capital': capital + }) + + # 开仓信号 + elif prev_position == 0 and signal != 0: + # 计算可买股数(假设全仓交易) + shares = int(capital / current_price) + if shares > 0: + position = shares * signal + capital -= shares * current_price + trades.append({ + 'date': date, + 'action': 'BUY', + 'price': current_price, + 'shares': shares * signal, + 'capital': capital + }) + + # 更新持仓市值 + portfolio_value = capital + position * current_price + + # 记录结果 + backtest_results.loc[date, 'capital'] = portfolio_value + backtest_results.loc[date, 'position'] = position + backtest_results.loc[date, 'price'] = current_price + + # 计算日收益率 + if i > 0: + prev_value = backtest_results['capital'].iloc[i - 1] + if prev_value > 0: + backtest_results.loc[date, 'returns'] = (portfolio_value - prev_value) / prev_value + + return backtest_results, trades + + def calculate_metrics(self, backtest_results, trades): + """ + 计算回测指标 + """ + returns = backtest_results['returns'].replace([np.inf, -np.inf], np.nan).dropna() + + if len(returns) == 0: + return { + '总收益率': 0, + '年化收益率': 0, + '波动率': 0, + '夏普比率': 0, + '最大回撤': 0, + '胜率': 0, + '平均交易收益': 0, + '交易次数': 0, + '最终资金': self.initial_capital + } + + total_return = (backtest_results['capital'].iloc[-1] - self.initial_capital) / self.initial_capital + annual_return = (1 + total_return) ** (252 / len(returns)) - 1 + + # 波动率 + volatility = returns.std() * np.sqrt(252) + + # 夏普比率(假设无风险利率为3%) + risk_free_rate = 0.03 + sharpe_ratio = (annual_return - risk_free_rate) / volatility if volatility > 0 else 0 + + # 最大回撤 + cumulative_returns = (1 + returns).cumprod() + peak = cumulative_returns.expanding().max() + drawdown = (cumulative_returns - peak) / peak + max_drawdown = drawdown.min() + + # 交易统计 + trade_returns = [] + buy_trades = [t for t in trades if t['action'] == 'BUY'] + sell_trades = [t for t in trades if t['action'] == 'SELL'] + + for i in range(min(len(buy_trades), len(sell_trades))): + buy = buy_trades[i] + sell = sell_trades[i] + trade_return = (sell['price'] - buy['price']) / buy['price'] + trade_returns.append(trade_return) + + win_rate = len([r for r in trade_returns if r > 0]) / len(trade_returns) if trade_returns else 0 + avg_trade_return = np.mean(trade_returns) if trade_returns else 0 + + metrics = { + '总收益率': total_return, + '年化收益率': annual_return, + '波动率': volatility, + '夏普比率': sharpe_ratio, + '最大回撤': max_drawdown, + '胜率': win_rate, + '平均交易收益': avg_trade_return, + '交易次数': len(trades), + '最终资金': backtest_results['capital'].iloc[-1] + } + + return metrics + + def plot_backtest_results(self, backtest_results, metrics, stock_code, output_dir): + """ + 绘制回测结果图表 + """ + fig, (ax1, ax2, ax3) = plt.subplots(3, 1, figsize=(15, 12)) + + # 1. 资金曲线 + ax1.plot(backtest_results.index, backtest_results['capital'], + linewidth=2, label='策略资金曲线', color='#1f77b4') + ax1.axhline(y=self.initial_capital, color='red', linestyle='--', + label=f'初始资金 ({self.initial_capital:,.0f}元)') + ax1.set_ylabel('资金 (元)', fontsize=12) + ax1.legend() + ax1.grid(True, alpha=0.3) + ax1.set_title(f'{stock_code} Kronos模型回测结果', fontsize=14, fontweight='bold') + + # 2. 收益率曲线 + cumulative_returns = (1 + backtest_results['returns'].fillna(0)).cumprod() + ax2.plot(backtest_results.index, cumulative_returns, + linewidth=2, label='策略累计收益', color='#2ca02c') + + # 基准收益(买入持有) + price_returns = backtest_results['price'].pct_change().fillna(0) + benchmark_returns = (1 + price_returns).cumprod() + ax2.plot(backtest_results.index, benchmark_returns, + linewidth=2, label='基准收益(买入持有)', color='#ff7f0e', alpha=0.7) + + ax2.set_ylabel('累计收益', fontsize=12) + ax2.legend() + ax2.grid(True, alpha=0.3) + + # 3. 回撤曲线 + peak = cumulative_returns.expanding().max() + drawdown = (cumulative_returns - peak) / peak + ax3.fill_between(backtest_results.index, drawdown, 0, + alpha=0.3, color='red', label='回撤') + ax3.set_ylabel('回撤', fontsize=12) + ax3.set_xlabel('日期', fontsize=12) + ax3.legend() + ax3.grid(True, alpha=0.3) + + # 添加指标文本 + metrics_text = ( + f"总收益率: {metrics['总收益率']:.2%}\n" + f"年化收益率: {metrics['年化收益率']:.2%}\n" + f"夏普比率: {metrics['夏普比率']:.2f}\n" + f"最大回撤: {metrics['最大回撤']:.2%}\n" + f"胜率: {metrics['胜率']:.2%}\n" + f"交易次数: {metrics['交易次数']}\n" + f"最终资金: {metrics['最终资金']:,.0f}元" + ) + + ax1.text(0.02, 0.98, metrics_text, transform=ax1.transAxes, fontsize=10, + verticalalignment='top', bbox=dict(boxstyle="round,pad=0.3", + facecolor="lightyellow", alpha=0.8)) + + plt.tight_layout() + + # 保存图表 + os.makedirs(output_dir, exist_ok=True) + chart_file = os.path.join(output_dir, f'{stock_code}_backtest_results.png') + plt.savefig(chart_file, dpi=300, bbox_inches='tight') + print(f"📊 回测图表已保存: {chart_file}") + + plt.show() + + def run_complete_backtest(self, stock_code, output_dir, threshold=0.02): + """ + 运行完整的回测流程 + """ + print(f"🎯 开始 {stock_code} 回测分析") + print("=" * 50) + + try: + # 1. 加载数据 + print("步骤1: 加载历史数据和预测数据...") + hist_df = self.load_historical_data(stock_code) + pred_df = self.load_predictions(stock_code) + + # 2. 计算交易信号 + print("步骤2: 计算交易信号...") + combined_df = self.calculate_trading_signals(hist_df, pred_df, threshold) + + # 3. 运行回测 + print("步骤3: 运行回测...") + backtest_results, trades = self.run_backtest(combined_df) + + # 4. 计算指标 + print("步骤4: 计算回测指标...") + metrics = self.calculate_metrics(backtest_results, trades) + + # 5. 绘制结果 + print("步骤5: 生成回测图表...") + self.plot_backtest_results(backtest_results, metrics, stock_code, output_dir) + + # 6. 打印详细报告 + print("\n" + "=" * 70) + print(f"📊 {stock_code} 回测报告") + print("=" * 70) + for key, value in metrics.items(): + if isinstance(value, float): + if '率' in key or '收益' in key or '回撤' in key: + print(f" {key}: {value:.2%}") + else: + print(f" {key}: {value:.2f}") + else: + print(f" {key}: {value}") + + print(f"\n交易记录 (共{len(trades)}次交易):") + for i, trade in enumerate(trades[-10:], 1): # 显示最后10次交易 + print(f" 交易{i}: {trade['date'].strftime('%Y-%m-%d')} " + f"{trade['action']} {abs(trade['shares'])}股 @ {trade['price']:.2f}元") + + return metrics, backtest_results, trades + + except Exception as e: + print(f"❌ 回测过程中出现错误: {e}") + import traceback + traceback.print_exc() + return None, None, None + + +def main(): + """ + 主函数:运行Kronos模型回测 + """ + # 配置参数 + BACKTEST_CONFIG = { + "stock_code": "000831", # 要回测的股票代码 + "data_dir": r"D:\lianghuajiaoyi\Kronos\examples\data", # 历史数据目录 + "model_dir": r"D:\lianghuajiaoyi\Kronos\examples\yuce", # 模型预测结果目录 + "output_dir": r"D:\lianghuajiaoyi\Kronos\examples\backtest", # 回测结果输出目录 + "initial_capital": 100000, # 初始资金 + "threshold": 0.02 # 交易阈值(2%) + } + + print("🤖 Kronos模型回测系统") + print("=" * 50) + print(f"回测股票: {BACKTEST_CONFIG['stock_code']}") + print(f"初始资金: {BACKTEST_CONFIG['initial_capital']:,.0f}元") + print(f"交易阈值: {BACKTEST_CONFIG['threshold']:.1%}") + print() + + # 创建回测器并运行 + backtester = KronosBacktester( + data_dir=BACKTEST_CONFIG["data_dir"], + model_dir=BACKTEST_CONFIG["model_dir"], + initial_capital=BACKTEST_CONFIG["initial_capital"] + ) + + metrics, results, trades = backtester.run_complete_backtest( + stock_code=BACKTEST_CONFIG["stock_code"], + output_dir=BACKTEST_CONFIG["output_dir"], + threshold=BACKTEST_CONFIG["threshold"] + ) + + if metrics: + print(f"\n✅ {BACKTEST_CONFIG['stock_code']} 回测完成!") + print(f"📁 结果保存在: {BACKTEST_CONFIG['output_dir']}") + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/examples/yuce/000021_comprehensive_analysis_report.json b/examples/yuce/000021_comprehensive_analysis_report.json new file mode 100644 index 0000000..956297b --- /dev/null +++ b/examples/yuce/000021_comprehensive_analysis_report.json @@ -0,0 +1,60 @@ +{ + "timestamp": "2025-10-10 16:09:38", + "stock_code": "000021", + "market_analysis": { + "overall_is_main_uptrend": false, + "overall_trend_strength": 0.5, + "market_status": "未知", + "detailed_analysis": {} + }, + "sector_analysis": { + "industry": "消费电子", + "matched_sectors": [], + "main_sector": { + "sector": "传统行业", + "momentum": 0.5, + "description": "无热门概念" + }, + "is_sector_hot": false, + "resonance_score": 0.5, + "sector_count": 0 + }, + "macro_analysis": { + "us_rate_cycle": { + "current_rate": 4.25, + "trend": "降息周期", + "recent_cut": "2025年9月降息25个基点", + "expected_cuts_2025": 2, + "expected_cuts_2026": 2, + "impact_on_emerging_markets": "positive", + "usd_index_support": 95.0, + "analysis": "美联储开启宽松周期,利好全球流动性" + }, + "domestic_policy": { + "monetary_policy": "稳健偏松", + "fiscal_policy": "积极财政", + "market_liquidity": "合理充裕", + "industrial_policy": "设备更新、以旧换新", + "employment_policy": "稳就业政策加力", + "analysis": "政策组合拳发力,经济稳中向好" + }, + "industry_policy": { + "robot_policy": "机器人产业政策支持", + "chip_policy": "国产替代加速推进", + "AI_policy": "人工智能发展规划", + "low_altitude": "低空经济发展规划" + }, + "global_liquidity_outlook": "改善", + "overall_macro_score": 0.75 + }, + "fundamental_analysis": { + "company_name": "未知", + "business_areas": [], + "recent_developments": [], + "growth_drivers": [], + "risk_factors": [], + "investment_rating": "中性", + "fundamental_score": 0.5 + }, + "adjustment_factor": 1.04545 +} \ No newline at end of file diff --git a/examples/yuce/000021_optimized_prediction.png b/examples/yuce/000021_optimized_prediction.png new file mode 100644 index 0000000..1599c3e Binary files /dev/null and b/examples/yuce/000021_optimized_prediction.png differ diff --git a/examples/yuce/002354_comprehensive_analysis_report.json b/examples/yuce/002354_comprehensive_analysis_report.json new file mode 100644 index 0000000..6b4c3c9 --- /dev/null +++ b/examples/yuce/002354_comprehensive_analysis_report.json @@ -0,0 +1,60 @@ +{ + "timestamp": "2025-10-01 01:55:50", + "stock_code": "002354", + "market_analysis": { + "overall_is_main_uptrend": false, + "overall_trend_strength": 0.5, + "market_status": "未知", + "detailed_analysis": {} + }, + "sector_analysis": { + "industry": "互联网服务", + "matched_sectors": [], + "main_sector": { + "sector": "传统行业", + "momentum": 0.5, + "description": "无热门概念" + }, + "is_sector_hot": false, + "resonance_score": 0.5, + "sector_count": 0 + }, + "macro_analysis": { + "us_rate_cycle": { + "current_rate": 4.25, + "trend": "降息周期", + "recent_cut": "2025年9月降息25个基点", + "expected_cuts_2025": 2, + "expected_cuts_2026": 2, + "impact_on_emerging_markets": "positive", + "usd_index_support": 95.0, + "analysis": "美联储开启宽松周期,利好全球流动性" + }, + "domestic_policy": { + "monetary_policy": "稳健偏松", + "fiscal_policy": "积极财政", + "market_liquidity": "合理充裕", + "industrial_policy": "设备更新、以旧换新", + "employment_policy": "稳就业政策加力", + "analysis": "政策组合拳发力,经济稳中向好" + }, + "industry_policy": { + "robot_policy": "机器人产业政策支持", + "chip_policy": "国产替代加速推进", + "AI_policy": "人工智能发展规划", + "low_altitude": "低空经济发展规划" + }, + "global_liquidity_outlook": "改善", + "overall_macro_score": 0.75 + }, + "fundamental_analysis": { + "company_name": "未知", + "business_areas": [], + "recent_developments": [], + "growth_drivers": [], + "risk_factors": [], + "investment_rating": "中性", + "fundamental_score": 0.5 + }, + "adjustment_factor": 1.04545 +} \ No newline at end of file diff --git a/examples/yuce/002354_optimized_prediction.png b/examples/yuce/002354_optimized_prediction.png new file mode 100644 index 0000000..5d1120d Binary files /dev/null and b/examples/yuce/002354_optimized_prediction.png differ diff --git a/examples/yuce/300207_comprehensive_analysis_report.json b/examples/yuce/300207_comprehensive_analysis_report.json new file mode 100644 index 0000000..2e028ef --- /dev/null +++ b/examples/yuce/300207_comprehensive_analysis_report.json @@ -0,0 +1,70 @@ +{ + "timestamp": "2025-10-01 01:54:37", + "stock_code": "300207", + "market_analysis": { + "overall_is_main_uptrend": false, + "overall_trend_strength": 0.5, + "market_status": "未知", + "detailed_analysis": {} + }, + "sector_analysis": { + "industry": "电池", + "matched_sectors": [ + { + "sector": "新能源", + "momentum": 0.6, + "limit_up_stocks": 8, + "is_active": true, + "description": "光伏、储能" + } + ], + "main_sector": { + "sector": "新能源", + "momentum": 0.6, + "limit_up_stocks": 8, + "is_active": true, + "description": "光伏、储能" + }, + "is_sector_hot": true, + "resonance_score": 0.6, + "sector_count": 1 + }, + "macro_analysis": { + "us_rate_cycle": { + "current_rate": 4.25, + "trend": "降息周期", + "recent_cut": "2025年9月降息25个基点", + "expected_cuts_2025": 2, + "expected_cuts_2026": 2, + "impact_on_emerging_markets": "positive", + "usd_index_support": 95.0, + "analysis": "美联储开启宽松周期,利好全球流动性" + }, + "domestic_policy": { + "monetary_policy": "稳健偏松", + "fiscal_policy": "积极财政", + "market_liquidity": "合理充裕", + "industrial_policy": "设备更新、以旧换新", + "employment_policy": "稳就业政策加力", + "analysis": "政策组合拳发力,经济稳中向好" + }, + "industry_policy": { + "robot_policy": "机器人产业政策支持", + "chip_policy": "国产替代加速推进", + "AI_policy": "人工智能发展规划", + "low_altitude": "低空经济发展规划" + }, + "global_liquidity_outlook": "改善", + "overall_macro_score": 0.75 + }, + "fundamental_analysis": { + "company_name": "未知", + "business_areas": [], + "recent_developments": [], + "growth_drivers": [], + "risk_factors": [], + "investment_rating": "中性", + "fundamental_score": 0.5 + }, + "adjustment_factor": 1.0935407000000001 +} \ No newline at end of file diff --git a/examples/yuce/300207_optimized_prediction.png b/examples/yuce/300207_optimized_prediction.png new file mode 100644 index 0000000..53b33ca Binary files /dev/null and b/examples/yuce/300207_optimized_prediction.png differ diff --git a/examples/yuce/600580_comprehensive_analysis_report.json b/examples/yuce/600580_comprehensive_analysis_report.json new file mode 100644 index 0000000..b153ba0 --- /dev/null +++ b/examples/yuce/600580_comprehensive_analysis_report.json @@ -0,0 +1,96 @@ +{ + "timestamp": "2025-10-01 01:53:45", + "stock_code": "600580", + "market_analysis": { + "overall_is_main_uptrend": false, + "overall_trend_strength": 0.5, + "market_status": "未知", + "detailed_analysis": {} + }, + "sector_analysis": { + "industry": "电机", + "matched_sectors": [ + { + "sector": "机器人", + "momentum": 0.85, + "limit_up_stocks": 18, + "is_active": true, + "description": "人形机器人、工业自动化" + }, + { + "sector": "低空经济", + "momentum": 0.7, + "limit_up_stocks": 10, + "is_active": true, + "description": "无人机、eVTOL" + } + ], + "main_sector": { + "sector": "机器人", + "momentum": 0.85, + "limit_up_stocks": 18, + "is_active": true, + "description": "人形机器人、工业自动化" + }, + "is_sector_hot": true, + "resonance_score": 0.7749999999999999, + "sector_count": 2 + }, + "macro_analysis": { + "us_rate_cycle": { + "current_rate": 4.25, + "trend": "降息周期", + "recent_cut": "2025年9月降息25个基点", + "expected_cuts_2025": 2, + "expected_cuts_2026": 2, + "impact_on_emerging_markets": "positive", + "usd_index_support": 95.0, + "analysis": "美联储开启宽松周期,利好全球流动性" + }, + "domestic_policy": { + "monetary_policy": "稳健偏松", + "fiscal_policy": "积极财政", + "market_liquidity": "合理充裕", + "industrial_policy": "设备更新、以旧换新", + "employment_policy": "稳就业政策加力", + "analysis": "政策组合拳发力,经济稳中向好" + }, + "industry_policy": { + "robot_policy": "机器人产业政策支持", + "chip_policy": "国产替代加速推进", + "AI_policy": "人工智能发展规划", + "low_altitude": "低空经济发展规划" + }, + "global_liquidity_outlook": "改善", + "overall_macro_score": 0.75 + }, + "fundamental_analysis": { + "company_name": "卧龙电驱", + "business_areas": [ + "工业电机", + "机器人关键部件", + "航空电机", + "新能源汽车驱动" + ], + "recent_developments": [ + "与智元机器人实现双向持股,推进具身智能机器人技术研发", + "成立浙江龙飞电驱,专注航空电机业务", + "发布AI外骨骼机器人及灵巧手", + "布局高爆发关节模组、伺服驱动器等人形机器人关键部件" + ], + "growth_drivers": [ + "设备更新政策推动工业电机需求", + "机器人产业快速发展", + "低空经济政策支持", + "出海战略加速" + ], + "risk_factors": [ + "机器人业务营收占比仅2.71%,占比较低", + "工业需求景气度波动", + "原料价格波动风险" + ], + "investment_rating": "积极关注", + "fundamental_score": 0.7 + }, + "adjustment_factor": 1.1 +} \ No newline at end of file diff --git a/examples/yuce/600580_optimized_prediction.png b/examples/yuce/600580_optimized_prediction.png new file mode 100644 index 0000000..2b18657 Binary files /dev/null and b/examples/yuce/600580_optimized_prediction.png differ diff --git a/examples/yuce/historical_backtest.py b/examples/yuce/historical_backtest.py new file mode 100644 index 0000000..72bb534 --- /dev/null +++ b/examples/yuce/historical_backtest.py @@ -0,0 +1,384 @@ +# historical_backtest.py +import pandas as pd +import numpy as np +import matplotlib.pyplot as plt +import os +from datetime import datetime, timedelta +import warnings + +warnings.filterwarnings('ignore') + +# 设置中文字体 +plt.rcParams['font.sans-serif'] = ['SimHei'] +plt.rcParams['axes.unicode_minus'] = False + + +class HistoricalBacktester: + """ + 历史回测类:用历史数据验证模型预测效果 + """ + + def __init__(self, data_dir, initial_capital=100000): + self.data_dir = data_dir + self.initial_capital = initial_capital + + def load_historical_data(self, stock_code): + """加载历史数据""" + csv_file = os.path.join(self.data_dir, f"{stock_code}_stock_data.csv") + if not os.path.exists(csv_file): + raise FileNotFoundError(f"数据文件不存在: {csv_file}") + + df = pd.read_csv(csv_file, encoding='utf-8-sig') + + # 标准化列名 + column_mapping = { + '日期': 'date', + '开盘价': 'open', + '最高价': 'high', + '最低价': 'low', + '收盘价': 'close', + '成交量': 'volume', + '成交额': 'amount' + } + + for old_col, new_col in column_mapping.items(): + if old_col in df.columns: + df = df.rename(columns={old_col: new_col}) + + df['date'] = pd.to_datetime(df['date']) + df.set_index('date', inplace=True) + df = df.sort_index() + + print(f"✅ 加载历史数据: {len(df)} 条记录") + print(f"时间范围: {df.index.min()} 到 {df.index.max()}") + + return df + + def simulate_model_prediction(self, df, lookback_days=60, pred_days=30): + """ + 模拟模型预测:使用历史数据进行"预测",然后与实际结果对比 + """ + results = [] + + # 从数据中选取多个时间点进行"预测" + test_points = range(lookback_days, len(df) - pred_days, pred_days) + + for start_idx in test_points: + # 模拟预测:使用前lookback_days天数据"预测"后pred_days天 + historical_data = df.iloc[start_idx - lookback_days:start_idx] + actual_future = df.iloc[start_idx:start_idx + pred_days] + + # 简单的预测策略(这里应该替换为您的实际模型预测) + # 这里使用移动平均作为示例预测 + pred_close = self.simple_prediction(historical_data, pred_days) + + # 记录结果 + for i in range(min(len(pred_close), len(actual_future))): + results.append({ + 'date': actual_future.index[i], + 'actual_close': actual_future['close'].iloc[i], + 'predicted_close': pred_close[i], + 'lookback_start': historical_data.index[0], + 'prediction_date': historical_data.index[-1] + }) + + return pd.DataFrame(results) + + def simple_prediction(self, historical_data, pred_days): + """简单的预测方法(示例)""" + # 使用移动平均 + 随机波动作为预测 + last_price = historical_data['close'].iloc[-1] + avg_volatility = historical_data['close'].pct_change().std() + + predictions = [] + current_price = last_price + + for _ in range(pred_days): + # 模拟价格变化(正态分布) + change = np.random.normal(0, avg_volatility) + current_price = current_price * (1 + change) + predictions.append(current_price) + + return predictions + + def calculate_prediction_accuracy(self, results_df): + """计算预测准确率""" + results_df['error'] = results_df['predicted_close'] - results_df['actual_close'] + results_df['error_pct'] = results_df['error'] / results_df['actual_close'] + results_df['abs_error_pct'] = abs(results_df['error_pct']) + + accuracy_metrics = { + '平均绝对误差率': results_df['abs_error_pct'].mean(), + '预测准确率': (results_df['abs_error_pct'] < 0.05).mean(), # 误差小于5%算准确 + '方向准确率': (np.sign(results_df['predicted_close'].diff()) == + np.sign(results_df['actual_close'].diff())).mean(), + '相关系数': results_df['predicted_close'].corr(results_df['actual_close']) + } + + return accuracy_metrics + + def run_trading_strategy(self, results_df, threshold=0.03): + """基于预测结果运行交易策略""" + capital = self.initial_capital + position = 0 + trades = [] + portfolio_values = [] + + # 按日期排序 + results_df = results_df.sort_index() + + for date, row in results_df.iterrows(): + current_price = row['actual_close'] + predicted_price = row['predicted_close'] + predicted_return = (predicted_price - current_price) / current_price + + # 交易逻辑 + if position == 0 and predicted_return > threshold: + # 买入信号 + shares = int(capital / current_price) + if shares > 0: + position = shares + capital -= shares * current_price + trades.append({ + 'date': date, + 'action': 'BUY', + 'price': current_price, + 'shares': shares, + 'reason': f'预测上涨{predicted_return:.2%}' + }) + + elif position > 0 and predicted_return < -threshold: + # 卖出信号 + capital += position * current_price + trades.append({ + 'date': date, + 'action': 'SELL', + 'price': current_price, + 'shares': position, + 'reason': f'预测下跌{predicted_return:.2%}' + }) + position = 0 + + # 计算当前资产总值 + portfolio_value = capital + position * current_price + portfolio_values.append({ + 'date': date, + 'portfolio_value': portfolio_value, + 'position': position, + 'price': current_price + }) + + return pd.DataFrame(portfolio_values), trades + + def calculate_performance(self, portfolio_df, trades): + """计算策略表现""" + portfolio_df = portfolio_df.set_index('date') + returns = portfolio_df['portfolio_value'].pct_change().dropna() + + total_return = (portfolio_df['portfolio_value'].iloc[-1] - self.initial_capital) / self.initial_capital + + if len(returns) > 0: + annual_return = (1 + total_return) ** (252 / len(returns)) - 1 + volatility = returns.std() * np.sqrt(252) + sharpe_ratio = (annual_return - 0.03) / volatility if volatility > 0 else 0 + + # 最大回撤 + cumulative = (1 + returns).cumprod() + peak = cumulative.expanding().max() + drawdown = (cumulative - peak) / peak + max_drawdown = drawdown.min() + else: + annual_return = 0 + volatility = 0 + sharpe_ratio = 0 + max_drawdown = 0 + + # 买入持有策略对比 + buy_hold_return = (portfolio_df['price'].iloc[-1] - portfolio_df['price'].iloc[0]) / portfolio_df['price'].iloc[ + 0] + + performance = { + '策略总收益': total_return, + '策略年化收益': annual_return, + '买入持有收益': buy_hold_return, + '波动率': volatility, + '夏普比率': sharpe_ratio, + '最大回撤': max_drawdown, + '交易次数': len(trades), + '最终资金': portfolio_df['portfolio_value'].iloc[-1], + '超额收益': total_return - buy_hold_return + } + + return performance + + def plot_comparison(self, results_df, portfolio_df, stock_code, output_dir): + """绘制预测对比图表""" + fig, (ax1, ax2, ax3) = plt.subplots(3, 1, figsize=(15, 12)) + + # 1. 价格预测对比 + ax1.plot(results_df.index, results_df['actual_close'], + label='实际价格', color='blue', linewidth=2) + ax1.plot(results_df.index, results_df['predicted_close'], + label='预测价格', color='red', linestyle='--', alpha=0.7) + ax1.set_ylabel('价格 (元)') + ax1.legend() + ax1.set_title(f'{stock_code} - 价格预测 vs 实际走势', fontsize=14, fontweight='bold') + ax1.grid(True, alpha=0.3) + + # 2. 预测误差 + ax2.bar(results_df.index, results_df['error_pct'] * 100, + alpha=0.6, color='orange') + ax2.axhline(y=0, color='black', linestyle='-', linewidth=1) + ax2.set_ylabel('预测误差 (%)') + ax2.set_title('预测误差分析') + ax2.grid(True, alpha=0.3) + + # 3. 策略表现 + ax3.plot(portfolio_df['date'], portfolio_df['portfolio_value'], + label='策略资金曲线', color='green', linewidth=2) + ax3.axhline(y=self.initial_capital, color='red', linestyle='--', + label=f'初始资金 ({self.initial_capital:,.0f}元)') + + # 买入持有对比 + initial_shares = self.initial_capital / portfolio_df['price'].iloc[0] + buy_hold_values = portfolio_df['price'] * initial_shares + ax3.plot(portfolio_df['date'], buy_hold_values, + label='买入持有策略', color='blue', linestyle=':', alpha=0.7) + + ax3.set_ylabel('资金 (元)') + ax3.set_xlabel('日期') + ax3.legend() + ax3.set_title('策略表现对比') + ax3.grid(True, alpha=0.3) + + plt.tight_layout() + + # 保存图表 + os.makedirs(output_dir, exist_ok=True) + chart_file = os.path.join(output_dir, f'{stock_code}_historical_backtest.png') + plt.savefig(chart_file, dpi=300, bbox_inches='tight') + print(f"📊 历史回测图表已保存: {chart_file}") + + plt.show() + + def run_complete_backtest(self, stock_code, output_dir, lookback_days=60, pred_days=30, threshold=0.03): + """运行完整的历史回测""" + print(f"🎯 开始 {stock_code} 历史回测分析") + print("=" * 60) + + try: + # 1. 加载历史数据 + print("步骤1: 加载历史数据...") + df = self.load_historical_data(stock_code) + + # 2. 模拟模型预测 + print("步骤2: 模拟模型预测...") + results_df = self.simulate_model_prediction(df, lookback_days, pred_days) + + # 3. 计算预测准确率 + print("步骤3: 计算预测准确率...") + accuracy_metrics = self.calculate_prediction_accuracy(results_df) + + # 4. 运行交易策略 + print("步骤4: 运行交易策略...") + portfolio_df, trades = self.run_trading_strategy(results_df, threshold) + + # 5. 计算策略表现 + print("步骤5: 计算策略表现...") + performance = self.calculate_performance(portfolio_df, trades) + + # 6. 绘制结果 + print("步骤6: 生成回测图表...") + self.plot_comparison(results_df, portfolio_df, stock_code, output_dir) + + # 7. 打印报告 + print("\n" + "=" * 70) + print(f"📊 {stock_code} 历史回测报告") + print("=" * 70) + + print("\n🔍 预测准确率分析:") + for metric, value in accuracy_metrics.items(): + if isinstance(value, float): + print(f" {metric}: {value:.2%}") + else: + print(f" {metric}: {value:.4f}") + + print("\n💰 策略表现分析:") + for metric, value in performance.items(): + if isinstance(value, float): + if '收益' in metric or '回撤' in metric: + print(f" {metric}: {value:.2%}") + else: + print(f" {metric}: {value:.4f}") + else: + print(f" {metric}: {value}") + + print(f"\n📈 交易统计:") + print(f" 总交易次数: {len(trades)}") + print(f" 买入次数: {len([t for t in trades if t['action'] == 'BUY'])}") + print(f" 卖出次数: {len([t for t in trades if t['action'] == 'SELL'])}") + + if len(trades) > 0: + print(f"\n最近5次交易:") + for trade in trades[-5:]: + print(f" {trade['date'].strftime('%Y-%m-%d')} {trade['action']} " + f"{trade['shares']}股 @ {trade['price']:.2f}元 - {trade['reason']}") + + return accuracy_metrics, performance, results_df + + except Exception as e: + print(f"❌ 回测过程中出现错误: {e}") + import traceback + traceback.print_exc() + return None, None, None + + +def main(): + """主函数""" + # 配置参数 + BACKTEST_CONFIG = { + "stock_code": "300418", + "data_dir": r"D:\lianghuajiaoyi\Kronos\examples\data", + "output_dir": r"D:\lianghuajiaoyi\Kronos\examples\historical_backtest", + "initial_capital": 100000, + "lookback_days": 60, # 使用60天历史数据 + "pred_days": 30, # 预测30天 + "threshold": 0.03 # 3%的交易阈值 + } + + print("🤖 Kronos模型历史回测系统") + print("=" * 50) + print(f"回测股票: {BACKTEST_CONFIG['stock_code']}") + print(f"回看天数: {BACKTEST_CONFIG['lookback_days']}天") + print(f"预测天数: {BACKTEST_CONFIG['pred_days']}天") + print(f"初始资金: {BACKTEST_CONFIG['initial_capital']:,.0f}元") + print() + + # 创建回测器并运行 + backtester = HistoricalBacktester( + data_dir=BACKTEST_CONFIG["data_dir"], + initial_capital=BACKTEST_CONFIG["initial_capital"] + ) + + accuracy, performance, results = backtester.run_complete_backtest( + stock_code=BACKTEST_CONFIG["stock_code"], + output_dir=BACKTEST_CONFIG["output_dir"], + lookback_days=BACKTEST_CONFIG["lookback_days"], + pred_days=BACKTEST_CONFIG["pred_days"], + threshold=BACKTEST_CONFIG["threshold"] + ) + + if accuracy and performance: + print(f"\n✅ {BACKTEST_CONFIG['stock_code']} 历史回测完成!") + + # 简单结论 + if performance['超额收益'] > 0: + print("🎉 结论: 模型策略跑赢了买入持有策略!") + else: + print("⚠️ 结论: 模型策略未能跑赢买入持有策略。") + + print(f"📁 详细结果保存在: {BACKTEST_CONFIG['output_dir']}") + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/examples/yuce/market_analysis_report.json b/examples/yuce/market_analysis_report.json new file mode 100644 index 0000000..a1f1484 --- /dev/null +++ b/examples/yuce/market_analysis_report.json @@ -0,0 +1,41 @@ +{ + "timestamp": "2025-09-30 22:45:36", + "market_analysis": { + "is_main_uptrend": false, + "trend_strength": 0.5, + "market_status": "未知", + "support_level": null, + "resistance_level": null + }, + "sector_analysis": { + "industry": "电机", + "sector_momentum": 0.5, + "sector_limit_up_count": 0, + "is_sector_hot": false, + "resonance_score": 0.35 + }, + "macro_analysis": { + "us_rate_cycle": { + "current_rate": 4.25, + "trend": "降息周期", + "expected_cuts_2025": 2, + "expected_cuts_2026": 2, + "impact_on_emerging_markets": "positive", + "usd_index_support": 95.0 + }, + "domestic_policy": { + "monetary_policy": "宽松", + "fiscal_policy": "积极", + "market_liquidity": "充足", + "holiday_effect": { + "effect": "节前震荡,节后上涨概率大", + "historical_win_rate": 0.8, + "expected_return": 0.0227, + "period": "节后5个交易日" + } + }, + "global_liquidity_outlook": "改善", + "overall_macro_score": 0.7 + }, + "adjustment_factor": 1.00776 +} \ No newline at end of file