增加交易策略、交易指标、量化库代码等文件夹

This commit is contained in:
Win_home committed 2025-04-27 15:54:09 +08:00
1 parent ca3b209096
commit f57150dae8
589 files changed
+854346 -1757

No files matched your search

File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,5 @@
price,Ask,Bid,symbol,datetime,delta,close,open,high,low,volume,dj
"['6438.6', '6439.4', '6439.6', '6440.0', '6440.4', '6441.0', '6441.4', '6441.6', '6442.0', '6442.2', '6442.4', '6442.6', '6442.8', '6443.0', '6443.2', '6443.4', '6443.6', '6443.8', '6444.0', '6444.2', '6444.4', '6444.6', '6445.0', '6445.6', '6446.0', '6446.2', '6446.4', '6447.4', '6447.6', '6447.8', '6448.0', '6448.2', '6448.4', '6448.6', '6448.8', '6449.0', '6449.2', '6449.4', '6449.8', '6450.0', '6450.2', '6450.4', '6450.6', '6450.8', '6451.0', '6451.2', '6451.6', '6451.8', '6452.0', '6452.2', '6452.4', '6452.6', '6452.8', '6453.4', '6453.6', '6453.8', '6454.0', '6454.4', '6454.6', '6455.0', '6455.2', '6455.8', '6456.4', '6456.6', '6457.4', '6457.6', '6457.8', '6458.0', '6458.2', '6459.0', '6459.2', '6459.4', '6459.6', '6459.8', '6460.0', '6461.0', '6461.2', '6461.4', '6461.8', '6462.0', '6462.2', '6462.4', '6462.6', '6462.8', '6463.0', '6463.2', '6463.4', '6463.6', '6463.8', '6464.0', '6464.2', '6464.4', '6464.6', '6464.8', '6465.0', '6465.2', '6465.4', '6465.6', '6465.8', '6466.0', '6466.2', '6466.4', '6466.6', '6466.8', '6467.0', '6467.2', '6467.4', '6467.6', '6467.8', '6468.0', '6468.2', '6468.4', '6468.6', '6468.8', '6469.0', '6469.2', '6469.4', '6469.6', '6469.8', '6470.0', '6470.2', '6470.4', '6470.6', '6470.8', '6471.0', '6471.2', '6471.4', '6471.6', '6471.8', '6472.0', '6472.4', '6472.6', '6472.8', '6473.0', '6473.2', '6473.6', '6474.0', '6474.4', '6474.6', '6475.0', '6476.0']","[0, 20, 31, 0, 0, 0, 63, 0, 0, 26, 37, 22, 24, 0, 0, 44, 131, 14, 19, 0, 6, 26, 30, 32, 0, 0, 0, 56, 0, 21, 42, 67, 38, 35, 12, 11, 33, 50, 11, 40, 157, 7, 149, 40, 0, 47, 73, 13, 58, 33, 0, 22, 0, 24, 54, 17, 27, 26, 32, 0, 0, 72, 100, 0, 25, 0, 33, 25, 14, 9, 0, 15, 13, 27, 16, 19, 13, 15, 0, 95, 24, 79, 0, 12, 16, 20, 26, 14, 15, 13, 18, 0, 26, 43, 63, 42, 45, 75, 13, 33, 23, 73, 64, 10, 47, 78, 0, 32, 61, 96, 61, 0, 0, 49, 32, 74, 49, 57, 23, 14, 11, 23, 35, 0, 61, 12, 13, 4, 2, 85, 70, 51, 36, 26, 4, 0, 137, 0, 27, 0, 30]","[19, 0, 0, 26, 31, 20, 0, 31, 17, 48, 52, 46, 0, 28, 18, 13, 27, 0, 17, 29, 0, 0, 0, 16, 48, 14, 51, 23, 13, 132, 137, 47, 11, 39, 16, 27, 0, 0, 38, 68, 52, 27, 0, 25, 43, 107, 0, 0, 45, 0, 42, 0, 30, 0, 0, 6, 34, 0, 41, 32, 20, 82, 0, 7, 6, 19, 0, 59, 46, 0, 28, 0, 0, 30, 8, 25, 41, 0, 12, 76, 0, 9, 40, 14, 4, 21, 0, 49, 46, 4, 41, 19, 38, 65, 125, 64, 24, 14, 0, 25, 24, 55, 20, 11, 12, 75, 45, 18, 38, 56, 23, 27, 53, 36, 64, 32, 46, 18, 66, 35, 31, 7, 12, 15, 42, 0, 61, 0, 0, 35, 124, 0, 34, 13, 0, 50, 44, 99, 0, 35, 0]",IM2503,2025-03-10 09:35:00,255,6446.0,6455.8,6476.0,6438.6,10242,1
"['6422.6', '6423.0', '6423.2', '6423.6', '6423.8', '6424.0', '6424.4', '6424.8', '6425.0', '6425.4', '6425.8', '6426.0', '6426.2', '6426.4', '6426.6', '6426.8', '6427.0', '6427.2', '6427.4', '6427.6', '6427.8', '6428.0', '6428.2', '6428.4', '6428.6', '6428.8', '6429.0', '6429.2', '6429.4', '6429.6', '6429.8', '6430.0', '6430.2', '6430.4', '6430.8', '6431.0', '6431.2', '6431.4', '6431.6', '6431.8', '6432.0', '6432.2', '6432.4', '6432.6', '6432.8', '6433.0', '6433.2', '6433.4', '6433.6', '6433.8', '6434.0', '6434.2', '6434.4', '6434.6', '6434.8', '6435.0', '6435.8', '6436.0', '6436.2', '6436.4', '6437.0', '6437.2', '6437.4', '6437.8', '6438.0', '6438.2', '6438.4', '6438.6', '6438.8', '6439.0', '6439.2', '6439.4', '6439.6', '6439.8', '6440.0', '6440.2', '6440.4', '6440.6', '6440.8', '6441.0', '6441.2', '6441.4', '6441.6', '6441.8', '6442.2', '6442.4', '6442.6', '6443.0', '6443.2', '6443.6', '6443.8', '6444.0', '6444.2', '6444.6', '6444.8', '6445.0', '6445.2', '6445.8', '6446.2', '6446.6', '6446.8', '6447.2', '6447.4', '6447.8', '6448.0', '6448.2', '6448.4', '6448.6', '6449.2', '6449.4', '6449.6', '6449.8', '6450.0', '6450.2', '6450.4', '6450.8', '6451.0', '6451.6', '6451.8', '6452.0', '6452.2', '6452.4', '6453.0', '6453.2', '6453.4', '6454.0']","[0, 0, 20, 0, 0, 0, 19, 32, 107, 21, 0, 40, 86, 89, 61, 56, 93, 101, 61, 33, 41, 20, 21, 43, 27, 38, 0, 22, 42, 8, 0, 40, 0, 0, 29, 36, 18, 11, 0, 0, 52, 78, 48, 59, 19, 21, 30, 5, 51, 15, 18, 19, 25, 0, 39, 8, 0, 15, 0, 0, 28, 20, 0, 19, 29, 0, 0, 98, 80, 5, 29, 9, 32, 28, 10, 6, 0, 11, 38, 20, 0, 0, 5, 9, 12, 0, 96, 0, 7, 47, 18, 60, 35, 40, 28, 25, 22, 11, 0, 13, 41, 37, 25, 18, 11, 0, 65, 7, 0, 13, 0, 24, 62, 23, 0, 29, 0, 0, 30, 47, 69, 47, 25, 50, 8, 7]","[29, 9, 18, 30, 58, 63, 0, 40, 13, 57, 25, 59, 22, 73, 44, 67, 91, 8, 64, 28, 68, 7, 0, 89, 67, 0, 16, 0, 73, 0, 12, 119, 42, 33, 32, 59, 23, 6, 56, 3, 74, 5, 145, 41, 22, 21, 53, 8, 60, 15, 59, 26, 0, 7, 0, 57, 26, 90, 37, 14, 134, 14, 73, 13, 0, 44, 9, 29, 22, 12, 7, 38, 41, 3, 0, 0, 44, 0, 0, 0, 80, 88, 0, 0, 13, 11, 39, 34, 0, 19, 65, 17, 0, 16, 49, 65, 45, 0, 40, 0, 0, 0, 0, 0, 50, 22, 24, 15, 13, 11, 31, 0, 19, 14, 8, 41, 14, 12, 16, 8, 16, 122, 27, 34, 27, 0]",IM2503,2025-03-10 09:40:00,-606,6450.2,6446.6,6454.0,6422.6,8879,0,
"['6432.0', '6432.2', '6432.4', '6433.0', '6433.2', '6433.4', '6433.6', '6433.8', '6434.0', '6434.2', '6434.4', '6434.6', '6434.8', '6435.0', '6435.2', '6435.4', '6435.6', '6435.8', '6436.2', '6436.4', '6437.2', '6438.0', '6438.6', '6438.8', '6439.0', '6439.8', '6440.6', '6441.0', '6441.2', '6441.6', '6441.8', '6442.0', '6442.2', '6442.4', '6442.6', '6442.8', '6443.0', '6443.2', '6443.4', '6443.6', '6443.8', '6444.0', '6444.2', '6444.4', '6444.6', '6444.8', '6445.0', '6445.2', '6445.4', '6445.6', '6445.8', '6446.0', '6446.2', '6446.4', '6446.6', '6446.8', '6447.0', '6447.2', '6447.4', '6447.6', '6447.8', '6448.0', '6448.2', '6448.4', '6448.6', '6448.8', '6449.0', '6449.2', '6449.4', '6449.6', '6449.8', '6450.0', '6450.4', '6450.6', '6450.8', '6451.0', '6451.2', '6451.4', '6451.6', '6451.8', '6452.0', '6452.2', '6452.4', '6452.6', '6453.0', '6453.2', '6453.6', '6453.8', '6454.0', '6454.4', '6454.6', '6455.0']","[0, 0, 8, 19, 0, 13, 10, 43, 19, 22, 29, 0, 23, 14, 13, 19, 22, 1, 0, 6, 0, 0, 9, 13, 0, 0, 0, 0, 0, 16, 18, 12, 19, 14, 0, 8, 25, 0, 28, 0, 8, 16, 16, 3, 0, 14, 31, 4, 63, 24, 46, 67, 0, 50, 10, 44, 25, 47, 58, 43, 82, 38, 51, 38, 56, 101, 46, 4, 113, 61, 0, 20, 0, 17, 49, 25, 25, 49, 5, 0, 37, 50, 33, 7, 5, 0, 55, 18, 29, 15, 0, 7]","[51, 10, 0, 17, 26, 0, 48, 2, 6, 0, 3, 4, 24, 2, 23, 20, 7, 0, 2, 21, 38, 27, 8, 0, 8, 13, 11, 23, 25, 33, 46, 29, 0, 7, 4, 33, 14, 40, 13, 10, 13, 23, 27, 45, 13, 4, 8, 24, 31, 38, 20, 38, 21, 56, 59, 63, 35, 25, 19, 18, 37, 45, 26, 11, 64, 58, 58, 8, 0, 35, 23, 33, 17, 0, 51, 52, 21, 0, 34, 21, 0, 14, 8, 0, 0, 14, 42, 0, 12, 0, 37, 0]",IM2503,2025-03-10 09:45:00,79,6432.0,6449.6,6455.0,6432.0,4881,-1,
"['6419.8', '6420.0', '6420.2', '6420.4', '6420.6', '6420.8', '6421.0', '6421.2', '6421.4', '6421.6', '6421.8', '6422.0', '6422.2', '6422.4', '6422.6', '6423.0', '6423.2', '6423.4', '6423.6', '6424.2', '6424.4', '6424.6', '6424.8', '6425.0', '6425.2', '6425.4', '6426.0', '6426.2', '6426.4', '6426.6', '6426.8', '6427.0', '6427.2', '6427.4', '6427.6', '6427.8', '6428.0', '6428.2', '6428.6', '6428.8', '6429.0', '6429.2', '6429.4', '6429.6', '6429.8', '6430.0', '6430.2', '6430.4', '6430.6', '6430.8', '6431.0', '6431.2', '6431.4', '6431.6', '6431.8', '6432.0', '6432.4', '6432.6', '6432.8', '6433.0', '6433.4', '6433.6', '6433.8', '6434.0', '6434.2', '6434.4', '6434.6', '6434.8', '6435.0', '6435.2', '6435.4', '6435.6', '6435.8', '6436.0', '6436.2', '6436.4', '6436.6', '6436.8', '6437.0', '6437.2', '6437.4', '6437.6', '6437.8', '6438.0', '6438.2', '6438.4', '6438.6', '6438.8', '6439.0', '6439.2', '6439.4', '6439.6', '6439.8', '6440.0', '6440.2', '6440.4', '6440.6', '6441.0', '6441.2', '6441.6', '6442.0']","[39, 45, 0, 19, 28, 44, 35, 9, 7, 29, 25, 16, 60, 25, 0, 23, 9, 0, 3, 41, 0, 38, 0, 26, 9, 16, 0, 23, 4, 0, 0, 32, 28, 0, 9, 54, 0, 18, 17, 0, 37, 33, 25, 13, 6, 28, 25, 2, 2, 0, 31, 8, 15, 14, 19, 0, 34, 36, 17, 4, 7, 8, 21, 10, 0, 3, 22, 10, 4, 3, 0, 0, 9, 15, 13, 6, 20, 23, 36, 21, 55, 18, 68, 45, 12, 33, 25, 10, 24, 15, 34, 47, 39, 12, 0, 4, 24, 0, 6, 8, 10]","[49, 98, 41, 31, 24, 24, 155, 2, 5, 19, 0, 29, 31, 3, 29, 87, 3, 58, 0, 0, 19, 0, 10, 83, 3, 21, 31, 10, 3, 8, 24, 19, 51, 10, 23, 24, 42, 31, 1, 23, 20, 16, 20, 8, 0, 72, 20, 5, 23, 7, 13, 19, 4, 24, 38, 35, 10, 39, 13, 0, 10, 23, 17, 1, 11, 7, 14, 33, 16, 6, 19, 5, 2, 29, 0, 10, 35, 53, 33, 4, 7, 36, 20, 15, 15, 10, 11, 46, 17, 19, 34, 15, 13, 10, 8, 0, 5, 5, 0, 0, 16]",IM2503,2025-03-10 09:50:00,-340,6423.2,6431.8,6442.0,6419.8,4510,-3,
1 price Ask Bid symbol datetime delta close open high low volume dj
2 ['6438.6', '6439.4', '6439.6', '6440.0', '6440.4', '6441.0', '6441.4', '6441.6', '6442.0', '6442.2', '6442.4', '6442.6', '6442.8', '6443.0', '6443.2', '6443.4', '6443.6', '6443.8', '6444.0', '6444.2', '6444.4', '6444.6', '6445.0', '6445.6', '6446.0', '6446.2', '6446.4', '6447.4', '6447.6', '6447.8', '6448.0', '6448.2', '6448.4', '6448.6', '6448.8', '6449.0', '6449.2', '6449.4', '6449.8', '6450.0', '6450.2', '6450.4', '6450.6', '6450.8', '6451.0', '6451.2', '6451.6', '6451.8', '6452.0', '6452.2', '6452.4', '6452.6', '6452.8', '6453.4', '6453.6', '6453.8', '6454.0', '6454.4', '6454.6', '6455.0', '6455.2', '6455.8', '6456.4', '6456.6', '6457.4', '6457.6', '6457.8', '6458.0', '6458.2', '6459.0', '6459.2', '6459.4', '6459.6', '6459.8', '6460.0', '6461.0', '6461.2', '6461.4', '6461.8', '6462.0', '6462.2', '6462.4', '6462.6', '6462.8', '6463.0', '6463.2', '6463.4', '6463.6', '6463.8', '6464.0', '6464.2', '6464.4', '6464.6', '6464.8', '6465.0', '6465.2', '6465.4', '6465.6', '6465.8', '6466.0', '6466.2', '6466.4', '6466.6', '6466.8', '6467.0', '6467.2', '6467.4', '6467.6', '6467.8', '6468.0', '6468.2', '6468.4', '6468.6', '6468.8', '6469.0', '6469.2', '6469.4', '6469.6', '6469.8', '6470.0', '6470.2', '6470.4', '6470.6', '6470.8', '6471.0', '6471.2', '6471.4', '6471.6', '6471.8', '6472.0', '6472.4', '6472.6', '6472.8', '6473.0', '6473.2', '6473.6', '6474.0', '6474.4', '6474.6', '6475.0', '6476.0'] [0, 20, 31, 0, 0, 0, 63, 0, 0, 26, 37, 22, 24, 0, 0, 44, 131, 14, 19, 0, 6, 26, 30, 32, 0, 0, 0, 56, 0, 21, 42, 67, 38, 35, 12, 11, 33, 50, 11, 40, 157, 7, 149, 40, 0, 47, 73, 13, 58, 33, 0, 22, 0, 24, 54, 17, 27, 26, 32, 0, 0, 72, 100, 0, 25, 0, 33, 25, 14, 9, 0, 15, 13, 27, 16, 19, 13, 15, 0, 95, 24, 79, 0, 12, 16, 20, 26, 14, 15, 13, 18, 0, 26, 43, 63, 42, 45, 75, 13, 33, 23, 73, 64, 10, 47, 78, 0, 32, 61, 96, 61, 0, 0, 49, 32, 74, 49, 57, 23, 14, 11, 23, 35, 0, 61, 12, 13, 4, 2, 85, 70, 51, 36, 26, 4, 0, 137, 0, 27, 0, 30] [19, 0, 0, 26, 31, 20, 0, 31, 17, 48, 52, 46, 0, 28, 18, 13, 27, 0, 17, 29, 0, 0, 0, 16, 48, 14, 51, 23, 13, 132, 137, 47, 11, 39, 16, 27, 0, 0, 38, 68, 52, 27, 0, 25, 43, 107, 0, 0, 45, 0, 42, 0, 30, 0, 0, 6, 34, 0, 41, 32, 20, 82, 0, 7, 6, 19, 0, 59, 46, 0, 28, 0, 0, 30, 8, 25, 41, 0, 12, 76, 0, 9, 40, 14, 4, 21, 0, 49, 46, 4, 41, 19, 38, 65, 125, 64, 24, 14, 0, 25, 24, 55, 20, 11, 12, 75, 45, 18, 38, 56, 23, 27, 53, 36, 64, 32, 46, 18, 66, 35, 31, 7, 12, 15, 42, 0, 61, 0, 0, 35, 124, 0, 34, 13, 0, 50, 44, 99, 0, 35, 0] IM2503 2025-03-10 09:35:00 255 6446.0 6455.8 6476.0 6438.6 10242 1
3 ['6422.6', '6423.0', '6423.2', '6423.6', '6423.8', '6424.0', '6424.4', '6424.8', '6425.0', '6425.4', '6425.8', '6426.0', '6426.2', '6426.4', '6426.6', '6426.8', '6427.0', '6427.2', '6427.4', '6427.6', '6427.8', '6428.0', '6428.2', '6428.4', '6428.6', '6428.8', '6429.0', '6429.2', '6429.4', '6429.6', '6429.8', '6430.0', '6430.2', '6430.4', '6430.8', '6431.0', '6431.2', '6431.4', '6431.6', '6431.8', '6432.0', '6432.2', '6432.4', '6432.6', '6432.8', '6433.0', '6433.2', '6433.4', '6433.6', '6433.8', '6434.0', '6434.2', '6434.4', '6434.6', '6434.8', '6435.0', '6435.8', '6436.0', '6436.2', '6436.4', '6437.0', '6437.2', '6437.4', '6437.8', '6438.0', '6438.2', '6438.4', '6438.6', '6438.8', '6439.0', '6439.2', '6439.4', '6439.6', '6439.8', '6440.0', '6440.2', '6440.4', '6440.6', '6440.8', '6441.0', '6441.2', '6441.4', '6441.6', '6441.8', '6442.2', '6442.4', '6442.6', '6443.0', '6443.2', '6443.6', '6443.8', '6444.0', '6444.2', '6444.6', '6444.8', '6445.0', '6445.2', '6445.8', '6446.2', '6446.6', '6446.8', '6447.2', '6447.4', '6447.8', '6448.0', '6448.2', '6448.4', '6448.6', '6449.2', '6449.4', '6449.6', '6449.8', '6450.0', '6450.2', '6450.4', '6450.8', '6451.0', '6451.6', '6451.8', '6452.0', '6452.2', '6452.4', '6453.0', '6453.2', '6453.4', '6454.0'] [0, 0, 20, 0, 0, 0, 19, 32, 107, 21, 0, 40, 86, 89, 61, 56, 93, 101, 61, 33, 41, 20, 21, 43, 27, 38, 0, 22, 42, 8, 0, 40, 0, 0, 29, 36, 18, 11, 0, 0, 52, 78, 48, 59, 19, 21, 30, 5, 51, 15, 18, 19, 25, 0, 39, 8, 0, 15, 0, 0, 28, 20, 0, 19, 29, 0, 0, 98, 80, 5, 29, 9, 32, 28, 10, 6, 0, 11, 38, 20, 0, 0, 5, 9, 12, 0, 96, 0, 7, 47, 18, 60, 35, 40, 28, 25, 22, 11, 0, 13, 41, 37, 25, 18, 11, 0, 65, 7, 0, 13, 0, 24, 62, 23, 0, 29, 0, 0, 30, 47, 69, 47, 25, 50, 8, 7] [29, 9, 18, 30, 58, 63, 0, 40, 13, 57, 25, 59, 22, 73, 44, 67, 91, 8, 64, 28, 68, 7, 0, 89, 67, 0, 16, 0, 73, 0, 12, 119, 42, 33, 32, 59, 23, 6, 56, 3, 74, 5, 145, 41, 22, 21, 53, 8, 60, 15, 59, 26, 0, 7, 0, 57, 26, 90, 37, 14, 134, 14, 73, 13, 0, 44, 9, 29, 22, 12, 7, 38, 41, 3, 0, 0, 44, 0, 0, 0, 80, 88, 0, 0, 13, 11, 39, 34, 0, 19, 65, 17, 0, 16, 49, 65, 45, 0, 40, 0, 0, 0, 0, 0, 50, 22, 24, 15, 13, 11, 31, 0, 19, 14, 8, 41, 14, 12, 16, 8, 16, 122, 27, 34, 27, 0] IM2503 2025-03-10 09:40:00 -606 6450.2 6446.6 6454.0 6422.6 8879 0
4 ['6432.0', '6432.2', '6432.4', '6433.0', '6433.2', '6433.4', '6433.6', '6433.8', '6434.0', '6434.2', '6434.4', '6434.6', '6434.8', '6435.0', '6435.2', '6435.4', '6435.6', '6435.8', '6436.2', '6436.4', '6437.2', '6438.0', '6438.6', '6438.8', '6439.0', '6439.8', '6440.6', '6441.0', '6441.2', '6441.6', '6441.8', '6442.0', '6442.2', '6442.4', '6442.6', '6442.8', '6443.0', '6443.2', '6443.4', '6443.6', '6443.8', '6444.0', '6444.2', '6444.4', '6444.6', '6444.8', '6445.0', '6445.2', '6445.4', '6445.6', '6445.8', '6446.0', '6446.2', '6446.4', '6446.6', '6446.8', '6447.0', '6447.2', '6447.4', '6447.6', '6447.8', '6448.0', '6448.2', '6448.4', '6448.6', '6448.8', '6449.0', '6449.2', '6449.4', '6449.6', '6449.8', '6450.0', '6450.4', '6450.6', '6450.8', '6451.0', '6451.2', '6451.4', '6451.6', '6451.8', '6452.0', '6452.2', '6452.4', '6452.6', '6453.0', '6453.2', '6453.6', '6453.8', '6454.0', '6454.4', '6454.6', '6455.0'] [0, 0, 8, 19, 0, 13, 10, 43, 19, 22, 29, 0, 23, 14, 13, 19, 22, 1, 0, 6, 0, 0, 9, 13, 0, 0, 0, 0, 0, 16, 18, 12, 19, 14, 0, 8, 25, 0, 28, 0, 8, 16, 16, 3, 0, 14, 31, 4, 63, 24, 46, 67, 0, 50, 10, 44, 25, 47, 58, 43, 82, 38, 51, 38, 56, 101, 46, 4, 113, 61, 0, 20, 0, 17, 49, 25, 25, 49, 5, 0, 37, 50, 33, 7, 5, 0, 55, 18, 29, 15, 0, 7] [51, 10, 0, 17, 26, 0, 48, 2, 6, 0, 3, 4, 24, 2, 23, 20, 7, 0, 2, 21, 38, 27, 8, 0, 8, 13, 11, 23, 25, 33, 46, 29, 0, 7, 4, 33, 14, 40, 13, 10, 13, 23, 27, 45, 13, 4, 8, 24, 31, 38, 20, 38, 21, 56, 59, 63, 35, 25, 19, 18, 37, 45, 26, 11, 64, 58, 58, 8, 0, 35, 23, 33, 17, 0, 51, 52, 21, 0, 34, 21, 0, 14, 8, 0, 0, 14, 42, 0, 12, 0, 37, 0] IM2503 2025-03-10 09:45:00 79 6432.0 6449.6 6455.0 6432.0 4881 -1
5 ['6419.8', '6420.0', '6420.2', '6420.4', '6420.6', '6420.8', '6421.0', '6421.2', '6421.4', '6421.6', '6421.8', '6422.0', '6422.2', '6422.4', '6422.6', '6423.0', '6423.2', '6423.4', '6423.6', '6424.2', '6424.4', '6424.6', '6424.8', '6425.0', '6425.2', '6425.4', '6426.0', '6426.2', '6426.4', '6426.6', '6426.8', '6427.0', '6427.2', '6427.4', '6427.6', '6427.8', '6428.0', '6428.2', '6428.6', '6428.8', '6429.0', '6429.2', '6429.4', '6429.6', '6429.8', '6430.0', '6430.2', '6430.4', '6430.6', '6430.8', '6431.0', '6431.2', '6431.4', '6431.6', '6431.8', '6432.0', '6432.4', '6432.6', '6432.8', '6433.0', '6433.4', '6433.6', '6433.8', '6434.0', '6434.2', '6434.4', '6434.6', '6434.8', '6435.0', '6435.2', '6435.4', '6435.6', '6435.8', '6436.0', '6436.2', '6436.4', '6436.6', '6436.8', '6437.0', '6437.2', '6437.4', '6437.6', '6437.8', '6438.0', '6438.2', '6438.4', '6438.6', '6438.8', '6439.0', '6439.2', '6439.4', '6439.6', '6439.8', '6440.0', '6440.2', '6440.4', '6440.6', '6441.0', '6441.2', '6441.6', '6442.0'] [39, 45, 0, 19, 28, 44, 35, 9, 7, 29, 25, 16, 60, 25, 0, 23, 9, 0, 3, 41, 0, 38, 0, 26, 9, 16, 0, 23, 4, 0, 0, 32, 28, 0, 9, 54, 0, 18, 17, 0, 37, 33, 25, 13, 6, 28, 25, 2, 2, 0, 31, 8, 15, 14, 19, 0, 34, 36, 17, 4, 7, 8, 21, 10, 0, 3, 22, 10, 4, 3, 0, 0, 9, 15, 13, 6, 20, 23, 36, 21, 55, 18, 68, 45, 12, 33, 25, 10, 24, 15, 34, 47, 39, 12, 0, 4, 24, 0, 6, 8, 10] [49, 98, 41, 31, 24, 24, 155, 2, 5, 19, 0, 29, 31, 3, 29, 87, 3, 58, 0, 0, 19, 0, 10, 83, 3, 21, 31, 10, 3, 8, 24, 19, 51, 10, 23, 24, 42, 31, 1, 23, 20, 16, 20, 8, 0, 72, 20, 5, 23, 7, 13, 19, 4, 24, 38, 35, 10, 39, 13, 0, 10, 23, 17, 1, 11, 7, 14, 33, 16, 6, 19, 5, 2, 29, 0, 10, 35, 53, 33, 4, 7, 36, 20, 15, 15, 10, 11, 46, 17, 19, 34, 15, 13, 10, 8, 0, 5, 5, 0, 0, 16] IM2503 2025-03-10 09:50:00 -340 6423.2 6431.8 6442.0 6419.8 4510 -3
@@ -0,0 +1,220 @@
from flask import Flask, render_template, jsonify
import pandas as pd
import numpy as np
import os
import ast
import time
app = Flask(__name__)
# 加入邮件通知
import smtplib
from email.mime.text import MIMEText # 导入 MIMEText 类发送纯文本邮件
from email.mime.multipart import (
MIMEMultipart,
)
import akshare as ak
# from email.mime.application import MIMEApplication
# 配置邮件信息
receivers = ["[email protected]"] # 设置邮件接收人地址
subject = "TD_Simnow_Signal" # 设置邮件主题 订单流策略交易信号
# 配置邮件服务器信息
smtp_server = "smtp.qq.com" # 设置发送邮件的 SMTP 服务器地址
smtp_port = 465 # 设置发送邮件的 SMTP 服务器端口号,一般为 25 端口 465
sender = "[email protected]" # 设置发送邮件的邮箱地址
username = "[email protected]" # 设置发送邮件的邮箱用户名
password = "osjyjmbqrzxtbjbf" # zrmpcgttataabhjh,设置发送邮件的邮箱密码或授权码
last_sent_time = 0
time_period = 48
# current_dir = os.path.dirname(os.path.abspath(__file__))
# os.chdir(current_dir)
# print("已更改为新的工作目录:", current_dir)
# 获取当前工作目录
current_directory = os.getcwd()
print("当前工作目录:", current_directory)
# 设置新的工作目录
new_directory = "C:/simnow_trader/traderdata"
os.chdir(new_directory)
# 验证新的工作目录
updated_directory = os.getcwd()
print("已更改为新的工作目录:", updated_directory)
# 获取当前文件夹中所有包含"ofdata"字符的CSV文件
def get_csv_files():
files = {}
for filename in os.listdir():
if "ofdata" in filename and filename.endswith(".csv"):
files[filename] = os.path.join(os.getcwd(), filename)
return files
def send_mail(text):
global last_sent_time
# 检查时间间隔
current_time = time.time()
if current_time - last_sent_time < 60:
print("current_time:",current_time)
print("last_sent_time:",last_sent_time)
print("一分钟内已发送过邮件,本次跳过")
return # 直接退出,不执行发送
msg = MIMEMultipart()
msg["From"] = sender
msg["To"] = ";".join(receivers)
msg["Subject"] = subject
html_content = f"""
<html>
<body>
<p>以下是数据的最后一列:</p>
{text}
</body>
</html>
"""
msg.attach(MIMEText(html_content, 'html'))
smtp = smtplib.SMTP_SSL(smtp_server, smtp_port)
smtp.login(username, password)
smtp.sendmail(sender, receivers, msg.as_string())
smtp.quit()
# 根据文件路径加载数据,只读取前12列
def load_data(file_path):
df = pd.read_csv(file_path, usecols=range(12)) # 只读取前12列
df = df.drop_duplicates()
df["delta"] = df["delta"].astype(float)
df['datetime'] = pd.to_datetime(df['datetime'],format='mixed')#, dayfirst=True, format='mixed'
# 增加'delta累计'列
df['delta累计'] = df.groupby(df['datetime'].dt.date)['delta'].cumsum()
# 使用akshare获取5分钟k线的全部数据
futures_zh_minute_sina_df = ak.futures_zh_minute_sina(symbol=df["symbol"].iloc[-1], period="5")
futures_zh_minute_sina_df['datetime'] = pd.to_datetime(futures_zh_minute_sina_df['datetime'],format='mixed')
futures_zh_minute_sina_df['终极平滑值'],futures_zh_minute_sina_df['趋势方向'] = ultimate_smoother(futures_zh_minute_sina_df["close"],time_period)
# 设置索引
df = df.set_index('datetime')
futures_zh_minute_sina_df = futures_zh_minute_sina_df.set_index('datetime')
# 使用 join 进行对齐
df_new = futures_zh_minute_sina_df.join(df[['price', 'Ask', 'Bid', 'delta','dj','delta累计']], how='left')
# 重置索引(可选)
df_new = df_new.reset_index()
df_new['datetime'] = df_new['datetime'].dt.strftime("%Y-%m-%d %H:%M:%S")
# 增加'POC'列
df_new['POC'] = add_poc_column(df_new)
df_new['symbol'] = df["symbol"].iloc[-1]
cols = ['price', 'Ask', 'Bid', 'symbol','datetime','delta','close', 'open', 'high', 'low', 'volume','hold','dj','delta累计','POC', '终极平滑值', '趋势方向']
df_new = df_new[cols]
del futures_zh_minute_sina_df,df
if len(df_new) >=5*time_period and (df_new['趋势方向'].iloc[-1] != df_new['趋势方向'].iloc[-2]):
table_text = df_new.iloc[:,3:].tail(1).to_html(index=False) #price,Ask,Bid,symbol,datetime,delta,close,open,high,low,volume,dj
send_mail(table_text)
else:
pass
return df_new.iloc[-11:-1].to_dict(orient="records")
def safe_literal_eval(x):
"""带异常处理的安全转换"""
try:
return ast.literal_eval(x)
except:
return [] # 返回空列表作为占位符
def add_poc_column(df):
# 安全转换列数据
df['price'] = df['price'].apply(safe_literal_eval)
df['Ask'] = df['Ask'].apply(lambda x: list(map(int, safe_literal_eval(x))))
df['Bid'] = df['Bid'].apply(lambda x: list(map(int, safe_literal_eval(x))))
# 定义处理函数(带数据验证)
def find_poc(row):
# 验证三个列表长度一致且非空
if not (len(row['price']) == len(row['Ask']) == len(row['Bid']) > 0):
return None # 返回空值标记异常数据
sums = [a + b for a, b in zip(row['Ask'], row['Bid'])]
try:
max_index = sums.index(max(sums))
return row['price'][max_index]
except ValueError:
return None # 处理空求和列表情况
# 应用处理函数
df['POC'] = df.apply(find_poc, axis=1)
# 可选:统计异常数据
error_count = df['POC'].isnull().sum()
if error_count > 0:
print(f"警告:发现 {error_count} 行异常数据(已标记为NaN)")
return df['POC']
def ultimate_smoother(price, period):
# 初始化变量(修正角度单位为弧度)
a1 = np.exp(-1.414 * np.pi / period)
b1 = 2 * a1 * np.cos(1.414 * np.pi / period) # 将180改为np.pi
c2 = b1
c3 = -a1 ** 2
c1 = (1 + c2 - c3) / 4
# 准备输出序列
us = np.zeros(len(price))
us_new = np.zeros(len(price))
trend = [None]*(len(price))
ma_close = np.zeros(len(price))
# 前4个点用原始价格初始化
for i in range(len(price)):
if i < 4:
us[i] = price[i]
else:
# 应用递归公式
us[i] = (1 - c1) * price[i] + (2 * c1 - c2) * price[i-1] \
- (c1 + c3) * price[i-2] + c2 * us[i-1] + c3 * us[i-2]
us_new = np.around(us, decimals=2)
ma_close = price.rolling(window=5*period).mean()
if us_new[i]>price[i] and ma_close[i]>price[i]:
trend[i] = '空头趋势'
elif us_new[i]<price[i] and ma_close[i]<price[i]:
trend[i] = '多头趋势'
else:
trend[i] = '无趋势'
return us_new,trend
@app.route("/")
def index():
files = get_csv_files() # 获取所有符合条件的文件
# 默认显示第一个文件的数据
first_file = list(files.keys())[0] if files else None
data = load_data(files[first_file]) if first_file else []
return render_template("index.html", data=data, files=files, file_name=first_file)
@app.route("/data/<file_name>")
def switch_data(file_name):
files = get_csv_files() # 获取所有符合条件的文件
if file_name in files:
data = load_data(files[file_name])
return jsonify(data)
return jsonify({"error": "File not found"}), 404
if __name__ == "__main__":
app.run(host='0.0.0.0', port=5000, debug=True) # 监听所有网络接口
@@ -0,0 +1,251 @@
from flask import Flask, render_template, jsonify
import pandas as pd
import numpy as np
import os
import ast
import time
app = Flask(__name__)
# 加入邮件通知
import smtplib
from email.mime.text import MIMEText # 导入 MIMEText 类发送纯文本邮件
from email.mime.multipart import (
MIMEMultipart,
)
import akshare as ak
# from email.mime.application import MIMEApplication
# 配置邮件信息
receivers = ["[email protected]"] # 设置邮件接收人地址
subject = "TD_Simnow_Signal" # 设置邮件主题 订单流策略交易信号
# 配置邮件服务器信息
smtp_server = "smtp.qq.com" # 设置发送邮件的 SMTP 服务器地址
smtp_port = 465 # 设置发送邮件的 SMTP 服务器端口号,一般为 25 端口 465
sender = "[email protected]" # 设置发送邮件的邮箱地址
username = "[email protected]" # 设置发送邮件的邮箱用户名
password = "osjyjmbqrzxtbjbf" # zrmpcgttataabhjh,设置发送邮件的邮箱密码或授权码
last_sent_time = 0
time_period = 48
# current_dir = os.path.dirname(os.path.abspath(__file__))
# os.chdir(current_dir)
# print("已更改为新的工作目录:", current_dir)
# 获取当前工作目录
current_directory = os.getcwd()
print("当前工作目录:", current_directory)
# 设置新的工作目录
new_directory = "C:/simnow_trader/traderdata"
os.chdir(new_directory)
# 验证新的工作目录
updated_directory = os.getcwd()
print("已更改为新的工作目录:", updated_directory)
# 获取当前文件夹中所有包含"ofdata"字符的CSV文件
def get_csv_files():
files = {}
for filename in os.listdir():
if "ofdata" in filename and filename.endswith(".csv"):
files[filename] = os.path.join(os.getcwd(), filename)
return files
def send_mail(text):
global last_sent_time
# 检查时间间隔
current_time = time.time()
if current_time - last_sent_time < 60:
print("current_time:",current_time)
print("last_sent_time:",last_sent_time)
print("一分钟内已发送过邮件,本次跳过")
return # 直接退出,不执行发送
msg = MIMEMultipart()
msg["From"] = sender
msg["To"] = ";".join(receivers)
msg["Subject"] = subject
html_content = f"""
<html>
<body>
<p>以下是数据的最后一列:</p>
{text}
</body>
</html>
"""
msg.attach(MIMEText(html_content, 'html'))
smtp = smtplib.SMTP_SSL(smtp_server, smtp_port)
smtp.login(username, password)
smtp.sendmail(sender, receivers, msg.as_string())
smtp.quit()
# 根据文件路径加载数据,只读取前12列
def load_data(file_path):
df = pd.read_csv(file_path, usecols=range(12)) # 只读取前12列
df = df.drop_duplicates()
# 筛选 Ask 和 Bid 均不等于 [0] 的行
# mask_ask = df['Ask'] != [0] # Ask 列不等于 [0]
# mask_bid = df['Bid'] != [0] # Bid 列不等于 [0]
# df = df[mask_ask & mask_bid]
# 创建掩码,标记需要删除的行(Ask或Bid等于[0])
# mask = df['Ask'].apply(lambda x: x == [0]) | df['Bid'].apply(lambda x: x == [0])
# # 使用取反操作符~保留无需删除的行
# df = df[~mask]
# df = df[df['high'] != df['low']]
df["delta"] = df["delta"].astype(float)
df['datetime'] = pd.to_datetime(df['datetime'],format='mixed')#, dayfirst=True, format='mixed'
df['delta累计'] = df.groupby(df['datetime'].dt.date)['delta'].cumsum()
# 使用filter方法,itemwise=True确保按列进行操作
# filtered_df = df[(df['delta'] >= 300) | (df['delta'] <= -300) | (df['dj'] >= 5) | (df['dj'] <= -5)]
futures_zh_minute_sina_df = ak.futures_zh_minute_sina(symbol=df["symbol"].iloc[-1], period="5")
futures_zh_minute_sina_df['datetime'] = pd.to_datetime(futures_zh_minute_sina_df['datetime'],format='mixed')
futures_zh_minute_sina_df['终极平滑值'],futures_zh_minute_sina_df['趋势方向'] = ultimate_smoother(futures_zh_minute_sina_df["close"],time_period)
# 设置索引
df = df.set_index('datetime')
futures_zh_minute_sina_df = futures_zh_minute_sina_df.set_index('datetime')
# 使用 join 进行对齐
# df = df.join(futures_zh_minute_sina_df[['终极平滑值', '趋势方向']], how='left')
df_new = futures_zh_minute_sina_df.join(df[['price', 'Ask', 'Bid', 'delta','dj','delta累计']], how='left')
# df = df.join(futures_zh_minute_sina_df[['趋势方向']], how='left')
# 重置索引(可选)
df_new = df_new.reset_index()
# df = pd.merge(df,futures_zh_minute_sina_df[['datetime', '终极平滑值']], on='datetime', how='left' )
# df = pd.merge(df,futures_zh_minute_sina_df[['datetime', ]], on='datetime', how='left' )
# df['终极平滑值'],df['趋势方向'] = ultimate_smoother(df['close'],time_period)
df_new['datetime'] = df_new['datetime'].dt.strftime("%Y-%m-%d %H:%M:%S")
df_new['POC'] = add_poc_column(df_new)
df_new['symbol'] = df["symbol"].iloc[-1]
# print(df.tail(1))
# cols = df_new.columns.tolist()
# cols.insert(3, cols.pop(0))
cols = ['price', 'Ask', 'Bid', 'symbol','datetime','delta','close', 'open', 'high', 'low', 'volume','hold','dj','delta累计','POC', '终极平滑值', '趋势方向']
df_new = df_new[cols]
# print(cols)
del futures_zh_minute_sina_df,df
if len(df_new) >=5*time_period and (df_new['趋势方向'].iloc[-1] != df_new['趋势方向'].iloc[-2]):
table_text = df_new.iloc[:,3:].tail(1).to_html(index=False) #price,Ask,Bid,symbol,datetime,delta,close,open,high,low,volume,dj
send_mail(table_text)
# time.sleep(60)
else:
pass
return df_new.iloc[-11:-1].to_dict(orient="records")
# def add_poc_column(df):
# # 转换字符串列到实际列表
# df['price'] = df['price'].apply(ast.literal_eval)
# df['Ask'] = df['Ask'].apply(lambda x: list(map(int, ast.literal_eval(x))))
# df['Bid'] = df['Bid'].apply(lambda x: list(map(int, ast.literal_eval(x))))
# # 定义处理函数(向量化操作更高效)
# def find_poc(row):
# sums = [a + b for a, b in zip(row['Ask'], row['Bid'])]
# max_index = sums.index(max(sums))
# return row['price'][max_index]
# # 应用处理函数
# df['POC'] = df.apply(find_poc, axis=1)
# return df['POC']
def safe_literal_eval(x):
"""带异常处理的安全转换"""
try:
return ast.literal_eval(x)
except:
return [] # 返回空列表作为占位符
def add_poc_column(df):
# 安全转换列数据
df['price'] = df['price'].apply(safe_literal_eval)
df['Ask'] = df['Ask'].apply(lambda x: list(map(int, safe_literal_eval(x))))
df['Bid'] = df['Bid'].apply(lambda x: list(map(int, safe_literal_eval(x))))
# 定义处理函数(带数据验证)
def find_poc(row):
# 验证三个列表长度一致且非空
if not (len(row['price']) == len(row['Ask']) == len(row['Bid']) > 0):
return None # 返回空值标记异常数据
sums = [a + b for a, b in zip(row['Ask'], row['Bid'])]
try:
max_index = sums.index(max(sums))
return row['price'][max_index]
except ValueError:
return None # 处理空求和列表情况
# 应用处理函数
df['POC'] = df.apply(find_poc, axis=1)
# 可选:统计异常数据
error_count = df['POC'].isnull().sum()
if error_count > 0:
print(f"警告:发现 {error_count} 行异常数据(已标记为NaN)")
return df['POC']
def ultimate_smoother(price, period):
# 初始化变量(修正角度单位为弧度)
a1 = np.exp(-1.414 * np.pi / period)
b1 = 2 * a1 * np.cos(1.414 * np.pi / period) # 将180改为np.pi
c2 = b1
c3 = -a1 ** 2
c1 = (1 + c2 - c3) / 4
# 准备输出序列
us = np.zeros(len(price))
us_new = np.zeros(len(price))
trend = [None]*(len(price))
ma_close = np.zeros(len(price))
# 前4个点用原始价格初始化
for i in range(len(price)):
if i < 4:
us[i] = price[i]
else:
# 应用递归公式
us[i] = (1 - c1) * price[i] + (2 * c1 - c2) * price[i-1] \
- (c1 + c3) * price[i-2] + c2 * us[i-1] + c3 * us[i-2]
us_new = np.around(us, decimals=2)
ma_close = price.rolling(window=5*period).mean()
if us_new[i]>price[i] and ma_close[i]>price[i]:
trend[i] = '空头趋势'
elif us_new[i]<price[i] and ma_close[i]<price[i]:
trend[i] = '多头趋势'
else:
trend[i] = '无趋势'
return us_new,trend
@app.route("/")
def index():
files = get_csv_files() # 获取所有符合条件的文件
# 默认显示第一个文件的数据
first_file = list(files.keys())[0] if files else None
data = load_data(files[first_file]) if first_file else []
return render_template("index.html", data=data, files=files, file_name=first_file)
@app.route("/data/<file_name>")
def switch_data(file_name):
files = get_csv_files() # 获取所有符合条件的文件
if file_name in files:
data = load_data(files[file_name])
return jsonify(data)
return jsonify({"error": "File not found"}), 404
if __name__ == "__main__":
app.run(host='0.0.0.0', port=5000, debug=True) # 监听所有网络接口
@@ -0,0 +1,200 @@
from flask import Flask, render_template, jsonify
import pandas as pd
import numpy as np
import os
import ast
import time
app = Flask(__name__)
# 加入邮件通知
import smtplib
from email.mime.text import MIMEText # 导入 MIMEText 类发送纯文本邮件
from email.mime.multipart import (
MIMEMultipart,
)
import akshare as ak
# from email.mime.application import MIMEApplication
# 配置邮件信息
receivers = ["[email protected]"] # 设置邮件接收人地址
subject = "TD_Simnow_Signal" # 设置邮件主题 订单流策略交易信号
# 配置邮件服务器信息
smtp_server = "smtp.qq.com" # 设置发送邮件的 SMTP 服务器地址
smtp_port = 465 # 设置发送邮件的 SMTP 服务器端口号,一般为 25 端口 465
sender = "[email protected]" # 设置发送邮件的邮箱地址
username = "[email protected]" # 设置发送邮件的邮箱用户名
password = "osjyjmbqrzxtbjbf" # zrmpcgttataabhjh,设置发送邮件的邮箱密码或授权码
last_sent_time = 0
time_period = 60
# current_dir = os.path.dirname(os.path.abspath(__file__))
# os.chdir(current_dir)
# print("已更改为新的工作目录:", current_dir)
# 获取当前工作目录
current_directory = os.getcwd()
print("当前工作目录:", current_directory)
# 设置新的工作目录
new_directory = "C:/simnow_trader/traderdata"
os.chdir(new_directory)
# 验证新的工作目录
updated_directory = os.getcwd()
print("已更改为新的工作目录:", updated_directory)
# 获取当前文件夹中所有包含"ofdata"字符的CSV文件
def get_csv_files():
files = {}
for filename in os.listdir():
if "ofdata" in filename and filename.endswith(".csv"):
files[filename] = os.path.join(os.getcwd(), filename)
return files
def send_mail(text):
global last_sent_time
# 检查时间间隔
current_time = time.time()
if current_time - last_sent_time < 60:
print("current_time:",current_time)
print("last_sent_time:",last_sent_time)
print("一分钟内已发送过邮件,本次跳过")
return # 直接退出,不执行发送
msg = MIMEMultipart()
msg["From"] = sender
msg["To"] = ";".join(receivers)
msg["Subject"] = subject
html_content = f"""
<html>
<body>
<p>以下是数据的最后一列:</p>
{text}
</body>
</html>
"""
msg.attach(MIMEText(html_content, 'html'))
smtp = smtplib.SMTP_SSL(smtp_server, smtp_port)
smtp.login(username, password)
smtp.sendmail(sender, receivers, msg.as_string())
smtp.quit()
# 根据文件路径加载数据,只读取前12列
def load_data(file_path):
df = pd.read_csv(file_path, usecols=range(12)) # 只读取前12列
df = df.drop_duplicates(subset='datetime', keep='first').reset_index(drop=True)
df = df[df['high'] != df['low']]
df["delta"] = df["delta"].astype(float)
df['datetime'] = pd.to_datetime(df['datetime'],format='mixed')#, dayfirst=True, format='mixed'
df['delta累计'] = df.groupby(df['datetime'].dt.date)['delta'].cumsum()
df = df.fillna('缺值')
df['终极平滑值'],df['趋势方向'] = ultimate_smoother(df['close'],time_period)
df['datetime'] = df['datetime'].dt.strftime("%Y-%m-%d %H:%M:%S")
df['POC'] = add_poc_column(df)
print(df.tail(5))
# if len(df) >=5*time_period and (df['趋势方向'].iloc[-1] != df['趋势方向'].iloc[-2]):
# table_text = df.iloc[:,3:].tail(1).to_html(index=False) #price,Ask,Bid,symbol,datetime,delta,close,open,high,low,volume,dj
# send_mail(table_text)
# else:
# pass
return df.iloc[-60:].to_dict(orient="records")
def safe_literal_eval(x):
"""带异常处理的安全转换"""
try:
return ast.literal_eval(x)
except:
return [] # 返回空列表作为占位符
def add_poc_column(df):
# 安全转换列数据
df['price'] = df['price'].apply(safe_literal_eval)
df['Ask'] = df['Ask'].apply(lambda x: list(map(int, safe_literal_eval(x))))
df['Bid'] = df['Bid'].apply(lambda x: list(map(int, safe_literal_eval(x))))
# 定义处理函数(带数据验证)
def find_poc(row):
# 验证三个列表长度一致且非空
if not (len(row['price']) == len(row['Ask']) == len(row['Bid']) > 0):
return '缺值' # 返回空值标记异常数据
sums = [a + b for a, b in zip(row['Ask'], row['Bid'])]
try:
max_index = sums.index(max(sums))
return row['price'][max_index]
except ValueError:
return '缺值' # 处理空求和列表情况
# 应用处理函数
df['POC'] = df.apply(find_poc, axis=1)
# 可选:统计异常数据
error_count = df['POC'].isnull().sum()
if error_count > 0:
print(f"警告:发现 {error_count} 行异常数据(已标记为NaN)")
return df['POC']
def ultimate_smoother(price, period):
# 初始化变量(修正角度单位为弧度)
a1 = np.exp(-1.414 * np.pi / period)
b1 = 2 * a1 * np.cos(1.414 * np.pi / period) # 将180改为np.pi
c2 = b1
c3 = -a1 ** 2
c1 = (1 + c2 - c3) / 4
# 准备输出序列
us = np.zeros(len(price))
us_new = np.zeros(len(price))
trend = [None]*(len(price))
ma_close = np.zeros(len(price))
# 前4个点用原始价格初始化
for i in range(len(price)):
if i < 4:
us[i] = price[i]
else:
# 应用递归公式
us[i] = (1 - c1) * price[i] + (2 * c1 - c2) * price[i-1] \
- (c1 + c3) * price[i-2] + c2 * us[i-1] + c3 * us[i-2]
us_new = np.around(us, decimals=2)
ma_close = price.rolling(window=5*period).mean()
if us_new[i]>price[i] and ma_close[i]>price[i]:
trend[i] = '空头趋势'
elif us_new[i]<price[i] and ma_close[i]<price[i]:
trend[i] = '多头趋势'
else:
trend[i] = '无趋势'
return us_new,trend
@app.route("/")
def index():
files = get_csv_files() # 获取所有符合条件的文件
# 默认显示第一个文件的数据
first_file = list(files.keys())[0] if files else None
data = load_data(files[first_file]) if first_file else []
return render_template("index.html", data=data, files=files, file_name=first_file)
@app.route("/data/<file_name>")
def switch_data(file_name):
files = get_csv_files() # 获取所有符合条件的文件
if file_name in files:
data = load_data(files[file_name])
return jsonify(data)
return jsonify({"error": "File not found"}), 404
if __name__ == "__main__":
app.run(host='0.0.0.0', port=5000, debug=True) # 监听所有网络接口
@@ -0,0 +1,235 @@
from flask import Flask, render_template, jsonify
from flask_socketio import SocketIO
import pandas as pd
import numpy as np
import os
import ast
import time
from datetime import datetime
app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret!'
socketio = SocketIO(app)
# 加入邮件通知
import smtplib
from email.mime.text import MIMEText # 导入 MIMEText 类发送纯文本邮件
from email.mime.multipart import (
MIMEMultipart,
)
import akshare as ak
# from email.mime.application import MIMEApplication
# 配置邮件信息
receivers = ["[email protected]"] # 设置邮件接收人地址
subject = "TD_Simnow_Signal" # 设置邮件主题 订单流策略交易信号
# 配置邮件服务器信息
smtp_server = "smtp.qq.com" # 设置发送邮件的 SMTP 服务器地址
smtp_port = 465 # 设置发送邮件的 SMTP 服务器端口号,一般为 25 端口 465
sender = "[email protected]" # 设置发送邮件的邮箱地址
username = "[email protected]" # 设置发送邮件的邮箱用户名
password = "osjyjmbqrzxtbjbf" # zrmpcgttataabhjh,设置发送邮件的邮箱密码或授权码
last_sent_time = 0
time_period = 48
# current_dir = os.path.dirname(os.path.abspath(__file__))
# os.chdir(current_dir)
# print("已更改为新的工作目录:", current_dir)
# 获取当前工作目录
current_directory = os.getcwd()
print("当前工作目录:", current_directory)
# 设置新的工作目录
new_directory = r"C:\simnow_trader\traderdata"
os.chdir(new_directory)
# 验证新的工作目录
updated_directory = os.getcwd()
print("已更改为新的工作目录:", updated_directory)
# 获取当前文件夹中所有包含"ofdata"字符的CSV文件
def get_csv_files():
files = {}
for filename in os.listdir():
if "ofdata" in filename and filename.endswith(".csv"):
files[filename] = os.path.join(os.getcwd(), filename)
return files
def send_mail(text):
global last_sent_time
# 检查时间间隔
current_time = time.time()
if current_time - last_sent_time < 60:
print("current_time:",current_time)
print("last_sent_time:",last_sent_time)
print("一分钟内已发送过邮件,本次跳过")
return # 直接退出,不执行发送
msg = MIMEMultipart()
msg["From"] = sender
msg["To"] = ";".join(receivers)
msg["Subject"] = subject
html_content = f"""
<html>
<body>
<p>以下是数据的最后一列:</p>
{text}
</body>
</html>
"""
msg.attach(MIMEText(html_content, 'html'))
smtp = smtplib.SMTP_SSL(smtp_server, smtp_port)
smtp.login(username, password)
smtp.sendmail(sender, receivers, msg.as_string())
smtp.quit()
# 根据文件路径加载数据,只读取前12列
def load_data(file_path):
df = pd.read_csv(file_path, usecols=range(12)) # 只读取前12列
df = df.drop_duplicates(subset='datetime', keep='first').reset_index(drop=True)
df = df[df['high'] != df['low']]
df["delta"] = df["delta"].astype(float)
df['datetime'] = pd.to_datetime(df['datetime'],format='ISO8601')#, dayfirst=True, format='mixed'
df['delta累计'] = df.groupby(df['datetime'].dt.date)['delta'].cumsum()
df = df.fillna('缺值')
df['终极平滑值'],df['趋势方向'] = ultimate_smoother(df['close'],time_period)
df['datetime'] = df['datetime'].dt.strftime("%Y-%m-%d %H:%M:%S")
df['POC'] = add_poc_column(df)
print(df.tail(2))
if len(df) >=5*time_period and (df['趋势方向'].iloc[-1] != df['趋势方向'].iloc[-2]):
table_text = df.iloc[:,3:].tail(1).to_html(index=False) #price,Ask,Bid,symbol,datetime,delta,close,open,high,low,volume,dj
send_mail(table_text)
else:
pass
return df.iloc[-60:].to_dict(orient="records")
def safe_literal_eval(x):
"""带异常处理的安全转换"""
try:
return ast.literal_eval(x)
except:
return [] # 返回空列表作为占位符
def add_poc_column(df):
# 安全转换列数据
df['price'] = df['price'].apply(safe_literal_eval)
df['Ask'] = df['Ask'].apply(lambda x: list(map(int, safe_literal_eval(x))))
df['Bid'] = df['Bid'].apply(lambda x: list(map(int, safe_literal_eval(x))))
# 定义处理函数(带数据验证)
def find_poc(row):
# 验证三个列表长度一致且非空
if not (len(row['price']) == len(row['Ask']) == len(row['Bid']) > 0):
return '缺值' # 返回空值标记异常数据
sums = [a + b for a, b in zip(row['Ask'], row['Bid'])]
try:
max_index = sums.index(max(sums))
return row['price'][max_index]
except ValueError:
return '缺值' # 处理空求和列表情况
# 应用处理函数
df['POC'] = df.apply(find_poc, axis=1)
# 可选:统计异常数据
error_count = df['POC'].isnull().sum()
if error_count > 0:
print(f"警告:发现 {error_count} 行异常数据(已标记为NaN)")
return df['POC']
def ultimate_smoother(price, period):
# 初始化变量(修正角度单位为弧度)
a1 = np.exp(-1.414 * np.pi / period)
b1 = 2 * a1 * np.cos(1.414 * np.pi / period) # 将180改为np.pi
c2 = b1
c3 = -a1 ** 2
c1 = (1 + c2 - c3) / 4
# 准备输出序列
us = np.zeros(len(price))
us_new = np.zeros(len(price))
trend = [None]*(len(price))
ma_close = np.zeros(len(price))
# 前4个点用原始价格初始化
for i in range(len(price)):
if i < 4:
us[i] = price[i]
else:
# 应用递归公式
us[i] = (1 - c1) * price[i] + (2 * c1 - c2) * price[i-1] \
- (c1 + c3) * price[i-2] + c2 * us[i-1] + c3 * us[i-2]
us_new = np.around(us, decimals=2)
ma_close = price.rolling(window=5*period).mean()
if us_new[i]>price[i] and ma_close[i]>price[i]:
trend[i] = '空头趋势'
elif us_new[i]<price[i] and ma_close[i]<price[i]:
trend[i] = '多头趋势'
else:
trend[i] = '无趋势'
return us_new,trend
@app.route("/")
def index():
return render_template("index.html")
@app.route("/api/data")
def get_data():
try:
files = get_csv_files()
data = {}
for symbol, filename in files.items():
loaded_data = load_data(filename)
if loaded_data:
data[symbol] = loaded_data
return jsonify(data)
except Exception as e:
return jsonify({"error": str(e)})
def should_update():
"""检查是否应该在当前时间更新数据"""
now = datetime.now()
# 检查是否是整点5分钟
if now.minute % 5 == 0:
# 检查是否在5秒内
if now.second < 5:
return True
return False
def background_thread():
"""后台线程,在每整点5分钟的5秒内发送数据更新"""
while True:
if should_update():
files = get_csv_files()
data = {}
for file_name, file_path in files.items():
data[file_name] = load_data(file_path)
socketio.emit('data_update', data)
print(f"数据更新完成 - {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
time.sleep(1) # 每秒检查一次
@socketio.on('connect')
def handle_connect():
print('Client connected')
# 启动后台线程
socketio.start_background_task(background_thread)
@socketio.on('disconnect')
def handle_disconnect():
print('Client disconnected')
if __name__ == "__main__":
socketio.run(app, host='0.0.0.0', port=5000, debug=True) # 监听所有网络接口
@@ -0,0 +1,220 @@
from flask import Flask, render_template, jsonify
import pandas as pd
import numpy as np
import os
import ast
import time
app = Flask(__name__)
# 加入邮件通知
import smtplib
from email.mime.text import MIMEText # 导入 MIMEText 类发送纯文本邮件
from email.mime.multipart import (
MIMEMultipart,
)
import akshare as ak
# from email.mime.application import MIMEApplication
# 配置邮件信息
receivers = ["[email protected]"] # 设置邮件接收人地址
subject = "TD_Simnow_Signal" # 设置邮件主题 订单流策略交易信号
# 配置邮件服务器信息
smtp_server = "smtp.qq.com" # 设置发送邮件的 SMTP 服务器地址
smtp_port = 465 # 设置发送邮件的 SMTP 服务器端口号,一般为 25 端口 465
sender = "[email protected]" # 设置发送邮件的邮箱地址
username = "[email protected]" # 设置发送邮件的邮箱用户名
password = "osjyjmbqrzxtbjbf" # zrmpcgttataabhjh,设置发送邮件的邮箱密码或授权码
last_sent_time = 0
time_period = 48
# current_dir = os.path.dirname(os.path.abspath(__file__))
# os.chdir(current_dir)
# print("已更改为新的工作目录:", current_dir)
# 获取当前工作目录
current_directory = os.getcwd()
print("当前工作目录:", current_directory)
# 设置新的工作目录
new_directory = "C:/simnow_trader/traderdata"
os.chdir(new_directory)
# 验证新的工作目录
updated_directory = os.getcwd()
print("已更改为新的工作目录:", updated_directory)
# 获取当前文件夹中所有包含"ofdata"字符的CSV文件
def get_csv_files():
files = {}
for filename in os.listdir():
if "ofdata" in filename and filename.endswith(".csv"):
files[filename] = os.path.join(os.getcwd(), filename)
return files
def send_mail(text):
global last_sent_time
# 检查时间间隔
current_time = time.time()
if current_time - last_sent_time < 60:
print("current_time:",current_time)
print("last_sent_time:",last_sent_time)
print("一分钟内已发送过邮件,本次跳过")
return # 直接退出,不执行发送
msg = MIMEMultipart()
msg["From"] = sender
msg["To"] = ";".join(receivers)
msg["Subject"] = subject
html_content = f"""
<html>
<body>
<p>以下是数据的最后一列:</p>
{text}
</body>
</html>
"""
msg.attach(MIMEText(html_content, 'html'))
smtp = smtplib.SMTP_SSL(smtp_server, smtp_port)
smtp.login(username, password)
smtp.sendmail(sender, receivers, msg.as_string())
smtp.quit()
# 根据文件路径加载数据,只读取前12列
def load_data(file_path):
df = pd.read_csv(file_path, usecols=range(12)) # 只读取前12列
df = df.drop_duplicates()
df["delta"] = df["delta"].astype(float)
df['datetime'] = pd.to_datetime(df['datetime'],format='mixed')#, dayfirst=True, format='mixed'
# 增加'delta累计'列
df['delta累计'] = df.groupby(df['datetime'].dt.date)['delta'].cumsum()
# # 使用akshare获取5分钟k线的全部数据
# df = ak.futures_zh_minute_sina(symbol=df["symbol"].iloc[-1], period="5")
# df['datetime'] = pd.to_datetime(df['datetime'],format='mixed')
# df['终极平滑值'],df['趋势方向'] = ultimate_smoother(df["close"],time_period)
df['终极平滑值'],df['趋势方向'] = ultimate_smoother(df['close'],time_period)
# # 设置索引
# df = df.set_index('datetime')
# df = df.set_index('datetime')
# # 使用 join 进行对齐
# df = df.join(df[['price', 'Ask', 'Bid', 'delta','dj','delta累计']], how='left')
# # 重置索引(可选)
# df = df.reset_index()
df['datetime'] = df['datetime'].dt.strftime("%Y-%m-%d %H:%M:%S")
# 增加'POC'列
df['POC'] = add_poc_column(df)
# df['symbol'] = df["symbol"].iloc[-1]
# cols = ['price', 'Ask', 'Bid', 'symbol','datetime','delta','close', 'open', 'high', 'low', 'volume','hold','dj','delta累计','POC', '终极平滑值', '趋势方向']
# df = df[cols]
# del df,df
if len(df) >=5*time_period and (df['趋势方向'].iloc[-1] != df['趋势方向'].iloc[-2]):
table_text = df.iloc[:,3:].tail(1).to_html(index=False) #price,Ask,Bid,symbol,datetime,delta,close,open,high,low,volume,dj
send_mail(table_text)
else:
pass
return df.iloc[-11:-1].to_dict(orient="records")
def safe_literal_eval(x):
"""带异常处理的安全转换"""
try:
return ast.literal_eval(x)
except:
return [] # 返回空列表作为占位符
def add_poc_column(df):
# 安全转换列数据
df['price'] = df['price'].apply(safe_literal_eval)
df['Ask'] = df['Ask'].apply(lambda x: list(map(int, safe_literal_eval(x))))
df['Bid'] = df['Bid'].apply(lambda x: list(map(int, safe_literal_eval(x))))
# 定义处理函数(带数据验证)
def find_poc(row):
# 验证三个列表长度一致且非空
if not (len(row['price']) == len(row['Ask']) == len(row['Bid']) > 0):
return None # 返回空值标记异常数据
sums = [a + b for a, b in zip(row['Ask'], row['Bid'])]
try:
max_index = sums.index(max(sums))
return row['price'][max_index]
except ValueError:
return None # 处理空求和列表情况
# 应用处理函数
df['POC'] = df.apply(find_poc, axis=1)
# 可选:统计异常数据
error_count = df['POC'].isnull().sum()
if error_count > 0:
print(f"警告:发现 {error_count} 行异常数据(已标记为NaN)")
return df['POC']
def ultimate_smoother(price, period):
# 初始化变量(修正角度单位为弧度)
a1 = np.exp(-1.414 * np.pi / period)
b1 = 2 * a1 * np.cos(1.414 * np.pi / period) # 将180改为np.pi
c2 = b1
c3 = -a1 ** 2
c1 = (1 + c2 - c3) / 4
# 准备输出序列
us = np.zeros(len(price))
us_new = np.zeros(len(price))
trend = [None]*(len(price))
ma_close = np.zeros(len(price))
# 前4个点用原始价格初始化
for i in range(len(price)):
if i < 4:
us[i] = price[i]
else:
# 应用递归公式
us[i] = (1 - c1) * price[i] + (2 * c1 - c2) * price[i-1] \
- (c1 + c3) * price[i-2] + c2 * us[i-1] + c3 * us[i-2]
us_new = np.around(us, decimals=2)
ma_close = price.rolling(window=5*period).mean()
if us_new[i]>price[i] and ma_close[i]>price[i]:
trend[i] = '空头趋势'
elif us_new[i]<price[i] and ma_close[i]<price[i]:
trend[i] = '多头趋势'
else:
trend[i] = '无趋势'
return us_new,trend
@app.route("/")
def index():
files = get_csv_files() # 获取所有符合条件的文件
# 默认显示第一个文件的数据
first_file = list(files.keys())[0] if files else None
data = load_data(files[first_file]) if first_file else []
return render_template("index.html", data=data, files=files, file_name=first_file)
@app.route("/data/<file_name>")
def switch_data(file_name):
files = get_csv_files() # 获取所有符合条件的文件
if file_name in files:
data = load_data(files[file_name])
return jsonify(data)
return jsonify({"error": "File not found"}), 404
if __name__ == "__main__":
app.run(host='0.0.0.0', port=5000, debug=True) # 监听所有网络接口
@@ -0,0 +1,136 @@
from flask import Flask, render_template, jsonify
import pandas as pd
import numpy as np
import os
import ast
app = Flask(__name__)
# current_dir = os.path.dirname(os.path.abspath(__file__))
# os.chdir(current_dir)
# print("已更改为新的工作目录:", current_dir)
# 获取当前工作目录
current_directory = os.getcwd()
print("当前工作目录:", current_directory)
# 设置新的工作目录
new_directory = "C:/simnow_trader/traderdata"
os.chdir(new_directory)
# 验证新的工作目录
updated_directory = os.getcwd()
print("已更改为新的工作目录:", updated_directory)
# 获取当前文件夹中所有包含"ofdata"字符的CSV文件
def get_csv_files():
files = {}
for filename in os.listdir():
if "ofdata" in filename and filename.endswith(".csv"):
files[filename] = os.path.join(os.getcwd(), filename)
return files
# 根据文件路径加载数据,只读取前12列
def load_data(file_path):
df = pd.read_csv(file_path, usecols=range(12)) # 只读取前12列
df["delta"] = df["delta"].astype(float)
df['datetime'] = pd.to_datetime(df['datetime'], format='mixed')
df['delta累计'] = df.groupby(df['datetime'].dt.date)['delta'].cumsum()
df['终极平滑值'],df['趋势方向'] = ultimate_smoother(df["close"],48)
df['datetime'] = df['datetime'].dt.strftime("%Y-%m-%d %H:%M:%S")
df['POC'] = add_poc_column(df)
return df.tail(20).to_dict(orient="records")
def safe_literal_eval(x):
"""带异常处理的安全转换"""
try:
return ast.literal_eval(x)
except:
return [] # 返回空列表作为占位符
def add_poc_column(df):
# 安全转换列数据
df['price'] = df['price'].apply(safe_literal_eval)
df['Ask'] = df['Ask'].apply(lambda x: list(map(int, safe_literal_eval(x))))
df['Bid'] = df['Bid'].apply(lambda x: list(map(int, safe_literal_eval(x))))
# 定义处理函数(带数据验证)
def find_poc(row):
# 验证三个列表长度一致且非空
if not (len(row['price']) == len(row['Ask']) == len(row['Bid']) > 0):
return 0 # 返回空值标记异常数据
sums = [a + b for a, b in zip(row['Ask'], row['Bid'])]
try:
max_index = sums.index(max(sums))
return row['price'][max_index]
except ValueError:
return 0 # 处理空求和列表情况
# 应用处理函数
df['POC'] = df.apply(find_poc, axis=1)
# 可选:统计异常数据
error_count = df['POC'].isnull().sum()
if error_count > 0:
print(f"警告:发现 {error_count} 行异常数据(已标记为NaN)")
return df['POC']
def ultimate_smoother(price, period):
# 初始化变量(修正角度单位为弧度)
a1 = np.exp(-1.414 * np.pi / period)
b1 = 2 * a1 * np.cos(1.414 * np.pi / period) # 将180改为np.pi
c2 = b1
c3 = -a1 ** 2
c1 = (1 + c2 - c3) / 4
# 准备输出序列
us = np.zeros(len(price))
us_new = np.zeros(len(price))
trend = [None]*(len(price))
ma_close = np.zeros(len(price))
# 前4个点用原始价格初始化
for i in range(len(price)):
if i < 4:
us[i] = price[i]
else:
# 应用递归公式
us[i] = (1 - c1) * price[i] + (2 * c1 - c2) * price[i-1] \
- (c1 + c3) * price[i-2] + c2 * us[i-1] + c3 * us[i-2]
us_new = np.around(us, decimals=2)
ma_close = price.rolling(window=period).mean()
if us_new[i]>price[i] and ma_close[i]>price[i]:
trend[i] = '空头趋势'
elif us_new[i]<price[i] and ma_close[i]<price[i]:
trend[i] = '多头趋势'
else:
trend[i] = '无趋势'
return us_new,trend
@app.route("/")
def index():
files = get_csv_files() # 获取所有符合条件的文件
# 默认显示第一个文件的数据
first_file = list(files.keys())[0] if files else None
data = load_data(files[first_file]) if first_file else []
return render_template("index.html", data=data, files=files, file_name=first_file)
@app.route("/data/<file_name>")
def switch_data(file_name):
files = get_csv_files() # 获取所有符合条件的文件
if file_name in files:
data = load_data(files[file_name])
return jsonify(data)
return jsonify({"error": "File not found"}), 404
if __name__ == "__main__":
app.run(host='0.0.0.0', port=5000, debug=True) # 监听所有网络接口
@@ -0,0 +1,222 @@
from flask import Flask, render_template, jsonify
from flask_socketio import SocketIO
import pandas as pd
import numpy as np
import os
import ast
import time
app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret!'
socketio = SocketIO(app)
# 加入邮件通知
import smtplib
from email.mime.text import MIMEText # 导入 MIMEText 类发送纯文本邮件
from email.mime.multipart import (
MIMEMultipart,
)
import akshare as ak
# from email.mime.application import MIMEApplication
# 配置邮件信息
receivers = ["[email protected]"] # 设置邮件接收人地址
subject = "TD_Simnow_Signal" # 设置邮件主题 订单流策略交易信号
# 配置邮件服务器信息
smtp_server = "smtp.qq.com" # 设置发送邮件的 SMTP 服务器地址
smtp_port = 465 # 设置发送邮件的 SMTP 服务器端口号,一般为 25 端口 465
sender = "[email protected]" # 设置发送邮件的邮箱地址
username = "[email protected]" # 设置发送邮件的邮箱用户名
password = "osjyjmbqrzxtbjbf" # zrmpcgttataabhjh,设置发送邮件的邮箱密码或授权码
last_sent_time = 0
time_period = 48
# current_dir = os.path.dirname(os.path.abspath(__file__))
# os.chdir(current_dir)
# print("已更改为新的工作目录:", current_dir)
# 获取当前工作目录
current_directory = os.getcwd()
print("当前工作目录:", current_directory)
# 设置新的工作目录
new_directory = r"C:\simnow_trader\traderdata"
os.chdir(new_directory)
# 验证新的工作目录
updated_directory = os.getcwd()
print("已更改为新的工作目录:", updated_directory)
# 获取当前文件夹中所有包含"ofdata"字符的CSV文件
def get_csv_files():
files = {}
for filename in os.listdir():
if "ofdata" in filename and filename.endswith(".csv"):
files[filename] = os.path.join(os.getcwd(), filename)
return files
def send_mail(text):
global last_sent_time
# 检查时间间隔
current_time = time.time()
if current_time - last_sent_time < 60:
print("current_time:",current_time)
print("last_sent_time:",last_sent_time)
print("一分钟内已发送过邮件,本次跳过")
return # 直接退出,不执行发送
msg = MIMEMultipart()
msg["From"] = sender
msg["To"] = ";".join(receivers)
msg["Subject"] = subject
html_content = f"""
<html>
<body>
<p>以下是数据的最后一列:</p>
{text}
</body>
</html>
"""
msg.attach(MIMEText(html_content, 'html'))
smtp = smtplib.SMTP_SSL(smtp_server, smtp_port)
smtp.login(username, password)
smtp.sendmail(sender, receivers, msg.as_string())
smtp.quit()
# 根据文件路径加载数据,只读取前12列
def load_data(file_path):
df = pd.read_csv(file_path, usecols=range(12)) # 只读取前12列
df = df.drop_duplicates(subset='datetime', keep='first').reset_index(drop=True)
df = df[df['high'] != df['low']]
df["delta"] = df["delta"].astype(float)
df['datetime'] = pd.to_datetime(df['datetime'],format='ISO8601')#, dayfirst=True,
df['delta累计'] = df.groupby(df['datetime'].dt.date)['delta'].cumsum()
df = df.fillna('缺值')
df['终极平滑值'],df['趋势方向'] = ultimate_smoother(df['close'],time_period)
df['datetime'] = df['datetime'].dt.strftime("%Y-%m-%d %H:%M:%S")
df['POC'] = add_poc_column(df)
print(df.tail(2))
# if len(df) >=5*time_period and (df['趋势方向'].iloc[-1] != df['趋势方向'].iloc[-2]):
# table_text = df.iloc[:,3:].tail(1).to_html(index=False) #price,Ask,Bid,symbol,datetime,delta,close,open,high,low,volume,dj
# send_mail(table_text)
# else:
# pass
return df.iloc[-60:].to_dict(orient="records")
def safe_literal_eval(x):
"""带异常处理的安全转换"""
try:
return ast.literal_eval(x)
except:
return [] # 返回空列表作为占位符
def add_poc_column(df):
# 安全转换列数据
df['price'] = df['price'].apply(safe_literal_eval)
df['Ask'] = df['Ask'].apply(lambda x: list(map(int, safe_literal_eval(x))))
df['Bid'] = df['Bid'].apply(lambda x: list(map(int, safe_literal_eval(x))))
# 定义处理函数(带数据验证)
def find_poc(row):
# 验证三个列表长度一致且非空
if not (len(row['price']) == len(row['Ask']) == len(row['Bid']) > 0):
return '缺值' # 返回空值标记异常数据
sums = [a + b for a, b in zip(row['Ask'], row['Bid'])]
try:
max_index = sums.index(max(sums))
return row['price'][max_index]
except ValueError:
return '缺值' # 处理空求和列表情况
# 应用处理函数
df['POC'] = df.apply(find_poc, axis=1)
# 可选:统计异常数据
error_count = df['POC'].isnull().sum()
if error_count > 0:
print(f"警告:发现 {error_count} 行异常数据(已标记为NaN)")
return df['POC']
def ultimate_smoother(price, period):
# 初始化变量(修正角度单位为弧度)
a1 = np.exp(-1.414 * np.pi / period)
b1 = 2 * a1 * np.cos(1.414 * np.pi / period) # 将180改为np.pi
c2 = b1
c3 = -a1 ** 2
c1 = (1 + c2 - c3) / 4
# 准备输出序列
us = np.zeros(len(price))
us_new = np.zeros(len(price))
trend = [None]*(len(price))
ma_close = np.zeros(len(price))
# 前4个点用原始价格初始化
for i in range(len(price)):
if i < 4:
us[i] = price[i]
else:
# 应用递归公式
us[i] = (1 - c1) * price[i] + (2 * c1 - c2) * price[i-1] \
- (c1 + c3) * price[i-2] + c2 * us[i-1] + c3 * us[i-2]
us_new = np.around(us, decimals=2)
ma_close = price.rolling(window=5*period).mean()
if us_new[i]>price[i] and ma_close[i]>price[i]:
trend[i] = '空头趋势'
elif us_new[i]<price[i] and ma_close[i]<price[i]:
trend[i] = '多头趋势'
else:
trend[i] = '无趋势'
return us_new,trend
@app.route("/")
def index():
return render_template("index.html")
@app.route("/api/data")
def get_data():
try:
files = get_csv_files()
data = {}
for symbol, filename in files.items():
loaded_data = load_data(filename)
if loaded_data:
data[symbol] = loaded_data
return jsonify(data)
except Exception as e:
return jsonify({"error": str(e)})
def background_thread():
"""后台线程,定期发送数据更新"""
while True:
files = get_csv_files()
data = {}
for file_name, file_path in files.items():
data[file_name] = load_data(file_path)
socketio.emit('data_update', data)
time.sleep(1) # 每秒更新一次
@socketio.on('connect')
def handle_connect():
print('Client connected')
# 启动后台线程
socketio.start_background_task(background_thread)
@socketio.on('disconnect')
def handle_disconnect():
print('Client disconnected')
if __name__ == "__main__":
socketio.run(app, host='0.0.0.0', port=5000, debug=True) # 监听所有网络接口
@@ -0,0 +1,234 @@
from flask import Flask, render_template, jsonify
import pandas as pd
import numpy as np
import os
import ast
import time
app = Flask(__name__)
# # from flask import Flask
# from flasgger import Swagger
# from flasgger import Talisman
# app = Flask(__name__)
# Talisman(app) # This will add X-Content-Type-Options among other headers.
# Swagger(app)
# 加入邮件通知
import smtplib
from email.mime.text import MIMEText # 导入 MIMEText 类发送纯文本邮件
from email.mime.multipart import (
MIMEMultipart,
)
import akshare as ak
# from email.mime.application import MIMEApplication
# 配置邮件信息
receivers = ["[email protected]"] # 设置邮件接收人地址
subject = "TD_Simnow_Signal" # 设置邮件主题 订单流策略交易信号
# 配置邮件服务器信息
smtp_server = "smtp.qq.com" # 设置发送邮件的 SMTP 服务器地址
smtp_port = 465 # 设置发送邮件的 SMTP 服务器端口号,一般为 25 端口 465
sender = "[email protected]" # 设置发送邮件的邮箱地址
username = "[email protected]" # 设置发送邮件的邮箱用户名
password = "osjyjmbqrzxtbjbf" # zrmpcgttataabhjh,设置发送邮件的邮箱密码或授权码
last_sent_time = 0
time_period = 48
# 获取当前工作目录
current_directory = os.getcwd()
print("当前工作目录:", current_directory)
# 设置新的工作目录
new_directory = "C:/simnow_trader/traderdata"
os.chdir(new_directory)
# 验证新的工作目录
updated_directory = os.getcwd()
print("已更改为新的工作目录:", updated_directory)
# 获取当前文件夹中所有包含"ofdata"字符的CSV文件
def get_csv_files():
files = {}
for filename in os.listdir():
if "ofdata" in filename and filename.endswith(".csv"):
files[filename] = os.path.join(os.getcwd(), filename)
return files
def send_mail(text):
global last_sent_time
# 检查时间间隔
current_time = time.time()
if current_time - last_sent_time < 60:
print("current_time:",current_time)
print("last_sent_time:",last_sent_time)
print("一分钟内已发送过邮件,本次跳过")
return # 直接退出,不执行发送
msg = MIMEMultipart()
msg["From"] = sender
msg["To"] = ";".join(receivers)
msg["Subject"] = subject
html_content = f"""
<html>
<body>
<p>以下是数据的最后一列:</p>
{text}
</body>
</html>
"""
msg.attach(MIMEText(html_content, 'html'))
smtp = smtplib.SMTP_SSL(smtp_server, smtp_port)
smtp.login(username, password)
smtp.sendmail(sender, receivers, msg.as_string())
smtp.quit()
# 根据文件路径加载数据,只读取前12列
def load_data(file_path):
df = pd.read_csv(file_path, usecols=range(12)) # 只读取前12列
df = df.drop_duplicates()
df["delta"] = df["delta"].astype(float)
df['datetime'] = pd.to_datetime(df['datetime'],format='mixed')#, dayfirst=True, format='mixed'
# 增加'delta累计'列和'POC'列
df['delta累计'] = df.groupby(df['datetime'].dt.date)['delta'].cumsum()
# 使用akshare获取5分钟k线的全部数据
symbol_name =df["symbol"].iloc[-1]
futures_zh_minute_sina_df = ak.futures_zh_minute_sina(symbol=symbol_name, period="5")
futures_zh_minute_sina_df['datetime'] = pd.to_datetime(futures_zh_minute_sina_df['datetime'],format='mixed')
futures_zh_minute_sina_df['终极平滑值'],futures_zh_minute_sina_df['趋势方向'] = ultimate_smoother(futures_zh_minute_sina_df["close"],time_period)
# 设置索引
df = df.set_index('datetime')
futures_zh_minute_sina_df = futures_zh_minute_sina_df.set_index('datetime')
# 使用 join 进行对齐
df = futures_zh_minute_sina_df.join(df[['price', 'Ask', 'Bid', 'delta','dj','delta累计']], how='left')
# 重置索引(可选)
df = df.reset_index()
# 修改symbol列全部值为统一值
df['symbol'] = symbol_name
# df['POC'] = add_poc_column(df)
# 重新排列数据并删除其他dataframe
cols = ['price', 'Ask', 'Bid', 'symbol','datetime','delta','close', 'open', 'high', 'low', 'volume','hold','dj','delta累计', '终极平滑值', '趋势方向']
df = df[cols]
# print(cols)
# datetime修改为字符串
df['datetime'] = df['datetime'].dt.strftime("%Y-%m-%d %H:%M:%S")
# del futures_zh_minute_sina_df,df
if len(df) >=5*time_period and (df['趋势方向'].iloc[-1] != df['趋势方向'].iloc[-2]):
table_text = df.iloc[:,3:].tail(1).to_html(index=False)
send_mail(table_text)
else:
pass
return df.iloc[-21:-1].to_dict(orient="records")
def safe_literal_eval(x):
"""带异常处理的安全转换"""
try:
return ast.literal_eval(x)
except:
return [] # 返回空列表作为占位符
def add_poc_column(df):
# 安全转换列数据
df['price'] = df['price'].apply(safe_literal_eval)
df['Ask'] = df['Ask'].apply(lambda x: list(map(int, safe_literal_eval(x))))
df['Bid'] = df['Bid'].apply(lambda x: list(map(int, safe_literal_eval(x))))
# 定义处理函数(带数据验证)
def find_poc(row):
# 验证三个列表长度一致且非空
if not (len(row['price']) == len(row['Ask']) == len(row['Bid']) > 0):
return None # 返回空值标记异常数据
sums = [a + b for a, b in zip(row['Ask'], row['Bid'])]
try:
max_index = sums.index(max(sums))
return row['price'][max_index]
except ValueError:
return None # 处理空求和列表情况
# 应用处理函数
df['POC'] = df.apply(find_poc, axis=1)
# 可选:统计异常数据
error_count = df['POC'].isnull().sum()
if error_count > 0:
print(f"警告:发现 {error_count} 行异常数据(已标记为NaN)")
return df['POC']
def ultimate_smoother(price, period):
# 初始化变量(修正角度单位为弧度)
a1 = np.exp(-1.414 * np.pi / period)
b1 = 2 * a1 * np.cos(1.414 * np.pi / period) # 将180改为np.pi
c2 = b1
c3 = -a1 ** 2
c1 = (1 + c2 - c3) / 4
# 准备输出序列
us = np.zeros(len(price))
us_new = np.zeros(len(price))
trend = [None]*(len(price))
ma_close = np.zeros(len(price))
# 前4个点用原始价格初始化
for i in range(len(price)):
if i < 4:
us[i] = price[i]
else:
# 应用递归公式
us[i] = (1 - c1) * price[i] + (2 * c1 - c2) * price[i-1] \
- (c1 + c3) * price[i-2] + c2 * us[i-1] + c3 * us[i-2]
us_new = np.around(us, decimals=2)
ma_close = price.rolling(window=5*period).mean()
if us_new[i]>price[i] and ma_close[i]>price[i]:
trend[i] = '空头趋势'
elif us_new[i]<price[i] and ma_close[i]<price[i]:
trend[i] = '多头趋势'
else:
trend[i] = '无趋势'
return us_new,trend
@app.route("/")
def index():
files = get_csv_files() # 获取所有符合条件的文件
# 默认显示第一个文件的数据
first_file = list(files.keys())[0] if files else None
data = load_data(files[first_file]) if first_file else []
return render_template("index.html", data=data, files=files, file_name=first_file)
@app.route("/data/<file_name>")
def switch_data(file_name):
files = get_csv_files() # 获取所有符合条件的文件
if file_name in files:
data = load_data(files[file_name])
return jsonify(data)
return jsonify({"error": "File not found"}), 404
if __name__ == "__main__":
app.run(host='0.0.0.0', port=5000, debug=True) # 监听所有网络接口
@@ -0,0 +1,67 @@
price,Ask,Bid,symbol,datetime,delta,close,open,high,low,volume,dj
"['3273.0', '3274.0', '3275.0', '3276.0']","[0, 2239, 2381, 3]","[864, 1357, 206, 0]",rb2505,2025-03-06 21:35:00,2196,3275.0,3275.0,3276.0,3273.0,7050,0
"['3271.0', '3272.0', '3273.0', '3274.0', '3275.0', '3276.0']","[0, 604, 1068, 2615, 2480, 433]","[1145, 5423, 3975, 2348, 312, 0]",rb2505,2025-03-06 21:40:00,-6003,3272.0,3275.0,3276.0,3271.0,20442,0,
"['3270.0', '3271.0', '3272.0', '3273.0']","[0, 946, 5050, 905]","[1459, 4097, 1983, 0]",rb2505,2025-03-06 21:45:00,-638,3273.0,3271.0,3273.0,3270.0,14440,0,
"['3271.0', '3272.0', '3273.0', '3274.0']","[0, 3303, 1202, 116]","[2189, 1249, 804, 0]",rb2505,2025-03-06 21:50:00,379,3271.0,3272.0,3274.0,3271.0,8863,0,
"['3271.0', '3272.0', '3273.0']","[0, 1259, 960]","[118, 1545, 0]",rb2505,2025-03-06 21:55:00,556,3271.0,3272.0,3273.0,3271.0,3882,0,
"['3270.0', '3271.0', '3272.0', '3273.0']","[0, 2564, 2309, 360]","[1248, 2593, 366, 0]",rb2505,2025-03-06 22:00:00,1026,3271.0,3272.0,3273.0,3270.0,9440,0,
"['3270.0', '3271.0', '3272.0', '3273.0', '3274.0', '3275.0', '3276.0']","[0, 1290, 703, 1821, 1779, 2845, 3380]","[248, 659, 459, 297, 539, 1570, 0]",rb2505,2025-03-06 22:05:00,8046,3276.0,3272.0,3276.0,3270.0,15590,1,
"['3272.0', '3273.0', '3274.0', '3275.0', '3276.0']","[0, 1190, 1918, 1595, 813]","[323, 1601, 1433, 1138, 0]",rb2505,2025-03-06 22:10:00,1021,3274.0,3276.0,3276.0,3272.0,10011,0,
"['3274.0', '3275.0', '3276.0']","[0, 3033, 117]","[858, 534, 0]",rb2505,2025-03-06 22:15:00,1758,3275.0,3275.0,3276.0,3274.0,4542,0,
"['3272.0', '3273.0', '3274.0', '3275.0', '3276.0', '3277.0']","[0, 226, 1038, 1347, 3527, 1104]","[216, 1675, 1744, 2605, 759, 0]",rb2505,2025-03-06 22:20:00,243,3273.0,3274.0,3277.0,3272.0,14244,0,
"['3272.0', '3273.0', '3274.0', '3275.0']","[0, 1631, 2274, 516]","[140, 1621, 455, 0]",rb2505,2025-03-06 22:25:00,2205,3274.0,3272.0,3275.0,3272.0,6637,0,
"['3273.0', '3274.0', '3275.0', '3276.0']","[0, 223, 1897, 739]","[86, 1447, 687, 0]",rb2505,2025-03-06 22:30:00,639,3274.0,3275.0,3276.0,3273.0,5082,0,
"['3271.0', '3272.0', '3273.0', '3274.0', '3275.0']","[0, 1111, 1004, 2859, 819]","[1924, 2892, 2861, 708, 0]",rb2505,2025-03-06 22:35:00,-2592,3274.0,3274.0,3275.0,3271.0,14482,0,
"['3273.0', '3274.0', '3275.0', '3276.0']","[0, 1193, 3446, 1192]","[789, 1104, 2067, 0]",rb2505,2025-03-06 22:40:00,1871,3275.0,3274.0,3276.0,3273.0,9926,0,
"['3274.0', '3275.0', '3276.0', '3277.0', '3278.0', '3279.0', '3280.0', '3281.0']","[0, 318, 2476, 1497, 1682, 3067, 7647, 2494]","[384, 524, 628, 2839, 2262, 4056, 4185, 531]",rb2505,2025-03-06 22:45:00,3772,3279.0,3275.0,3281.0,3274.0,34604,0,
"['3278.0', '3279.0', '3280.0', '3281.0', '3282.0']","[0, 1094, 5316, 2515, 3976]","[115, 3989, 3361, 3413, 1399]",rb2505,2025-03-06 22:50:00,624,3281.0,3279.0,3282.0,3278.0,25218,0,
"['3277.0', '3278.0', '3279.0', '3280.0', '3281.0', '3282.0', '3283.0']","[0, 208, 149, 1022, 935, 5026, 568]","[370, 1888, 2324, 2745, 3584, 3634, 0]",rb2505,2025-03-06 22:55:00,-6637,3277.0,3282.0,3283.0,3277.0,22560,0,
"['3277.0', '3278.0', '3279.0', '3280.0', '3281.0', '3282.0', '3283.0']","[0, 208, 149, 1022, 935, 5026, 568]","[370, 1888, 2324, 2745, 3584, 3634, 0]",rb2505,2025-03-06 22:55:00,-6637,3277.0,3282.0,3283.0,3277.0,22560,0
['3276.0'],[407],[0],rb2505,2025-03-07 09:00:00,407,3276.0,3276.0,3276.0,3276.0,407,0,
"['3263.0', '3264.0', '3265.0', '3266.0', '3267.0', '3268.0', '3269.0', '3270.0', '3271.0', '3272.0', '3273.0', '3274.0', '3275.0', '3276.0']","[0, 1185, 3264, 15510, 11309, 3093, 0, 0, 1860, 1562, 6083, 2622, 942, 224]","[415, 3808, 8500, 8651, 3437, 3420, 608, 3000, 1967, 2577, 5311, 943, 2063, 0]",rb2505,2025-03-07 09:05:00,2954,3266.0,3275.0,3276.0,3263.0,92524,0,
"['3252.0', '3253.0', '3254.0', '3255.0', '3256.0', '3257.0', '3258.0', '3259.0', '3260.0', '3261.0', '3262.0', '3263.0', '3264.0', '3265.0', '3266.0']","[5660, 5800, 8226, 3436, 6257, 19832, 16459, 2413, 2335, 0, 2177, 0, 768, 2194, 189]","[8407, 11202, 4431, 5969, 12929, 20176, 4761, 0, 9168, 1317, 4351, 2172, 682, 1041, 141]",rb2505,2025-03-07 09:10:00,-11001,3259.0,3266.0,3266.0,3252.0,163379,0,
"['3253.0', '3254.0', '3255.0', '3256.0', '3257.0', '3258.0', '3259.0']","[0, 1525, 2917, 5943, 8725, 5876, 157]","[1649, 3127, 4842, 6053, 8467, 1043, 0]",rb2505,2025-03-07 09:15:00,-38,3254.0,3258.0,3259.0,3253.0,50407,0,
"['3252.0', '3253.0', '3254.0', '3255.0', '3256.0', '3257.0', '3258.0', '3259.0']","[0, 1824, 3433, 825, 3263, 7570, 5900, 18]","[1528, 3068, 2182, 1690, 5805, 3707, 501, 0]",rb2505,2025-03-07 09:20:00,4352,3256.0,3254.0,3259.0,3252.0,41356,0,
"['3256.0', '3257.0', '3258.0', '3259.0', '3260.0', '3261.0', '3262.0']","[0, 1921, 4547, 2302, 3176, 5154, 2122]","[282, 2210, 1230, 1385, 4793, 1117, 0]",rb2505,2025-03-07 09:25:00,8205,3258.0,3256.0,3262.0,3256.0,30239,0,
"['3256.0', '3257.0', '3258.0', '3259.0', '3260.0']","[0, 2862, 2588, 2606, 63]","[2749, 5408, 4231, 767, 0]",rb2505,2025-03-07 09:30:00,-5036,3256.0,3259.0,3260.0,3256.0,21276,0,
"['3246.0', '3247.0', '3248.0', '3249.0', '3250.0', '3251.0', '3252.0', '3253.0', '3254.0', '3255.0', '3256.0', '3257.0']","[0, 4012, 6866, 9685, 7482, 3317, 2895, 3629, 7328, 2446, 3714, 1341]","[9209, 2310, 3079, 13939, 20493, 6274, 8208, 7267, 4002, 6069, 1820, 198]",rb2505,2025-03-07 09:35:00,-30153,3253.0,3256.0,3257.0,3246.0,136346,0,
"['3249.0', '3250.0', '3251.0', '3252.0', '3253.0', '3254.0', '3255.0']","[0, 1527, 7507, 2050, 6828, 3843, 806]","[389, 4946, 1997, 3250, 4207, 1199, 0]",rb2505,2025-03-07 09:40:00,6573,3253.0,3254.0,3255.0,3249.0,38549,0,
"['3252.0', '3253.0', '3254.0', '3255.0', '3256.0', '3257.0', '3258.0']","[0, 288, 5527, 3198, 3360, 3196, 2983]","[58, 860, 2514, 1333, 1923, 1216, 0]",rb2505,2025-03-07 09:45:00,10648,3255.0,3254.0,3258.0,3252.0,26456,0,
"['3253.0', '3254.0', '3255.0', '3256.0', '3257.0']","[0, 1155, 472, 4032, 913]","[399, 1245, 2938, 1161, 0]",rb2505,2025-03-07 09:50:00,829,3254.0,3255.0,3257.0,3253.0,12315,0,
"['3253.0', '3254.0', '3255.0', '3256.0', '3257.0', '3258.0', '3259.0']","[0, 2028, 1383, 1459, 1493, 2308, 736]","[954, 2568, 1343, 1502, 1324, 463, 0]",rb2505,2025-03-07 09:55:00,1253,3256.0,3255.0,3259.0,3253.0,17587,0,
"['3254.0', '3255.0', '3256.0', '3257.0', '3258.0', '3259.0']","[0, 885, 3178, 4388, 2676, 1129]","[212, 1329, 2996, 1018, 426, 0]",rb2505,2025-03-07 10:00:00,6275,3258.0,3255.0,3259.0,3254.0,18248,0,
"['3256.0', '3257.0', '3258.0', '3259.0', '3260.0']","[0, 2494, 3952, 2746, 1279]","[149, 3988, 3446, 2968, 0]",rb2505,2025-03-07 10:05:00,-80,3258.0,3258.0,3260.0,3256.0,21022,0,
"['3258.0', '3259.0', '3260.0', '3261.0', '3262.0']","[0, 957, 2858, 7038, 945]","[175, 1080, 3083, 2800, 0]",rb2505,2025-03-07 10:10:00,4660,3260.0,3258.0,3262.0,3258.0,18936,0,
"['3260.0', '3261.0', '3262.0', '3263.0', '3264.0', '3265.0', '3266.0', '3267.0', '3268.0']","[0, 1637, 1567, 6549, 4536, 1818, 6907, 4993, 4233]","[190, 854, 2038, 4706, 1553, 3127, 5673, 3900, 0]",rb2505,2025-03-07 10:15:00,10199,3265.0,3260.0,3268.0,3260.0,54287,0,
['3266.0'],[80],[0],rb2505,2025-03-07 10:20:00,80,3266.0,3266.0,3266.0,3266.0,80,0,
"['3261.0', '3262.0', '3263.0', '3264.0', '3265.0', '3266.0', '3267.0', '3268.0']","[0, 780, 3409, 1133, 2672, 1964, 2461, 779]","[212, 4376, 4176, 2743, 1521, 3407, 1804, 0]",rb2505,2025-03-07 10:35:00,-5041,3265.0,3266.0,3268.0,3261.0,31437,0,
"['3264.0', '3265.0', '3266.0', '3267.0', '3268.0', '3269.0', '3270.0', '3271.0', '3272.0', '3273.0']","[0, 353, 2722, 1474, 2631, 1435, 3091, 1513, 8997, 4883]","[132, 3627, 180, 0, 1526, 463, 2403, 6281, 8793, 897]",rb2505,2025-03-07 10:40:00,2797,3271.0,3266.0,3273.0,3264.0,51412,0,
"['3269.0', '3270.0', '3271.0', '3272.0', '3273.0', '3274.0', '3275.0']","[0, 1407, 3234, 4325, 2557, 895, 231]","[2051, 5992, 6301, 1713, 3361, 2545, 0]",rb2505,2025-03-07 10:45:00,-9314,3271.0,3271.0,3275.0,3269.0,34612,0,
"['3269.0', '3270.0', '3271.0', '3272.0']","[0, 2542, 2300, 2387]","[2024, 5753, 1855, 971]",rb2505,2025-03-07 10:50:00,-3374,3272.0,3272.0,3272.0,3269.0,17842,0,
"['3269.0', '3270.0', '3271.0', '3272.0', '3273.0', '3274.0', '3275.0', '3276.0', '3277.0', '3278.0', '3279.0']","[0, 1114, 716, 2953, 3012, 4006, 2649, 2924, 4621, 10292, 750]","[924, 2021, 2976, 4291, 3940, 5660, 1563, 4062, 9243, 1988, 0]",rb2505,2025-03-07 10:55:00,-3631,3269.0,3271.0,3279.0,3269.0,69827,0,
"['3267.0', '3268.0', '3269.0', '3270.0', '3271.0', '3272.0']","[0, 1781, 848, 3193, 2616, 797]","[1957, 2177, 2377, 3251, 1941, 0]",rb2505,2025-03-07 11:00:00,-2468,3270.0,3269.0,3272.0,3267.0,20966,0,
"['3268.0', '3269.0', '3270.0', '3271.0', '3272.0', '3273.0']","[0, 409, 1135, 1658, 2417, 519]","[917, 1532, 1375, 2421, 688, 0]",rb2505,2025-03-07 11:05:00,-795,3273.0,3270.0,3273.0,3268.0,13071,0,
"['3271.0', '3272.0', '3273.0', '3274.0', '3275.0', '3276.0']","[0, 551, 3054, 3865, 2735, 537]","[36, 1685, 3103, 1413, 347, 0]",rb2505,2025-03-07 11:10:00,4158,3273.0,3273.0,3276.0,3271.0,17326,0,
"['3269.0', '3270.0', '3271.0', '3272.0', '3273.0', '3274.0']","[0, 1771, 803, 1844, 1191, 2363]","[1621, 1721, 1509, 3674, 2024, 58]",rb2505,2025-03-07 11:15:00,-2635,3272.0,3273.0,3274.0,3269.0,18617,0,
"['3268.0', '3269.0', '3270.0', '3271.0', '3272.0', '3273.0', '3274.0']","[0, 101, 1254, 2094, 1226, 804, 832]","[266, 2152, 2364, 1824, 1307, 636, 0]",rb2505,2025-03-07 11:20:00,-2238,3270.0,3272.0,3274.0,3268.0,14862,0,
"['3269.0', '3270.0', '3271.0', '3272.0', '3273.0', '3274.0', '3275.0']","[0, 917, 1350, 955, 1510, 1116, 6]","[297, 2699, 843, 384, 2169, 3, 0]",rb2505,2025-03-07 11:25:00,-541,3275.0,3270.0,3275.0,3269.0,12269,0,
"['3269.0', '3270.0', '3271.0', '3272.0', '3273.0', '3274.0', '3275.0', '3276.0']","[0, 1615, 1687, 140, 83, 1395, 6826, 869]","[1197, 4148, 460, 994, 1727, 2875, 3938, 0]",rb2505,2025-03-07 11:30:00,-2724,3270.0,3274.0,3276.0,3269.0,27954,0,
['3270.0'],[0],[10],rb2505,2025-03-07 11:35:00,-10,3270.0,3270.0,3270.0,3270.0,10,0,
"['3268.0', '3269.0', '3270.0', '3271.0', '3272.0']","[0, 1159, 1947, 3762, 661]","[585, 2034, 3152, 1615, 0]",rb2505,2025-03-07 13:35:00,143,3270.0,3271.0,3272.0,3268.0,15009,0,
"['3268.0', '3269.0', '3270.0', '3271.0', '3272.0']","[0, 622, 2163, 1037, 33]","[221, 3960, 2227, 370, 0]",rb2505,2025-03-07 13:40:00,-2923,3269.0,3270.0,3272.0,3268.0,10707,0,
"['3264.0', '3265.0', '3266.0', '3267.0', '3268.0', '3269.0', '3270.0']","[0, 1124, 1753, 879, 377, 545, 374]","[158, 5009, 5001, 1935, 2505, 908, 0]",rb2505,2025-03-07 13:45:00,-10464,3265.0,3270.0,3270.0,3264.0,20568,-1,
"['3262.0', '3263.0', '3264.0', '3265.0', '3266.0', '3267.0']","[0, 1034, 4315, 2155, 5044, 1230]","[215, 5254, 4737, 2809, 1692, 0]",rb2505,2025-03-07 13:50:00,-929,3265.0,3265.0,3267.0,3262.0,28559,0,
"['3264.0', '3265.0', '3266.0', '3267.0', '3268.0', '3269.0', '3270.0']","[0, 1023, 1290, 2347, 821, 1827, 803]","[678, 1615, 1438, 432, 948, 36, 0]",rb2505,2025-03-07 13:55:00,2964,3266.0,3265.0,3270.0,3264.0,13260,0,
"['3266.0', '3267.0', '3268.0', '3269.0']","[154, 1705, 3083, 316]","[1531, 1207, 1310, 0]",rb2505,2025-03-07 14:00:00,1210,3267.0,3267.0,3269.0,3266.0,9339,0,
"['3256.0', '3257.0', '3258.0', '3259.0', '3260.0', '3261.0', '3262.0', '3263.0', '3264.0', '3265.0', '3266.0', '3267.0', '3268.0']","[0, 113, 412, 1536, 3195, 2820, 1223, 832, 1702, 1186, 1123, 180, 174]","[803, 3040, 1559, 1627, 3980, 3301, 899, 2599, 1468, 1453, 953, 111, 0]",rb2505,2025-03-07 14:05:00,-7297,3257.0,3267.0,3268.0,3256.0,36296,0,
"['3255.0', '3256.0', '3257.0', '3258.0', '3259.0', '3260.0']","[0, 7142, 12293, 8720, 2949, 555]","[3759, 7656, 9203, 2642, 827, 0]",rb2505,2025-03-07 14:10:00,7572,3258.0,3257.0,3260.0,3255.0,55762,0,
"['3255.0', '3256.0', '3257.0', '3258.0', '3259.0']","[0, 3358, 4138, 4316, 546]","[1611, 5572, 1726, 2036, 0]",rb2505,2025-03-07 14:15:00,1413,3256.0,3257.0,3259.0,3255.0,23303,0,
"['3254.0', '3255.0', '3256.0', '3257.0', '3258.0']","[0, 1270, 3528, 7590, 1545]","[2890, 6003, 4361, 2136, 0]",rb2505,2025-03-07 14:20:00,-1457,3257.0,3255.0,3258.0,3254.0,29323,0,
"['3256.0', '3257.0', '3258.0', '3259.0', '3260.0', '3261.0', '3262.0', '3263.0', '3264.0', '3265.0', '3266.0']","[0, 739, 1330, 941, 2998, 4917, 2955, 3201, 3964, 2103, 1628]","[318, 608, 52, 423, 1073, 611, 1765, 3611, 1504, 1623, 0]",rb2505,2025-03-07 14:25:00,13188,3264.0,3257.0,3266.0,3256.0,36540,2,
"['3259.0', '3260.0', '3261.0', '3262.0', '3263.0', '3264.0']","[0, 911, 3423, 2691, 350, 162]","[242, 3816, 1896, 2484, 1170, 0]",rb2505,2025-03-07 14:30:00,-2071,3260.0,3263.0,3264.0,3259.0,17145,0,
"['3255.0', '3256.0', '3257.0', '3258.0', '3259.0', '3260.0', '3261.0', '3262.0', '3263.0']","[0, 915, 2797, 849, 610, 53, 953, 1753, 828]","[909, 2863, 1997, 1745, 1111, 1214, 674, 1365, 0]",rb2505,2025-03-07 14:35:00,-3120,3256.0,3261.0,3263.0,3255.0,20636,0,
"['3255.0', '3256.0', '3257.0', '3258.0', '3259.0']","[0, 2133, 2113, 3459, 55]","[618, 1256, 2243, 629, 0]",rb2505,2025-03-07 14:40:00,3014,3256.0,3255.0,3259.0,3255.0,12506,0,
"['3253.0', '3254.0', '3255.0', '3256.0', '3257.0']","[366, 718, 5841, 7496, 1035]","[4146, 7433, 4375, 3639, 0]",rb2505,2025-03-07 14:45:00,-4137,3253.0,3256.0,3257.0,3253.0,35049,0,
"['3251.0', '3252.0', '3253.0', '3254.0', '3255.0', '3256.0']","[0, 10582, 4808, 4494, 724, 996]","[8116, 5025, 5497, 986, 121, 0]",rb2505,2025-03-07 14:50:00,1859,3252.0,3253.0,3256.0,3251.0,41349,0,
"['3252.0', '3253.0', '3254.0', '3255.0', '3256.0', '3257.0']","[0, 3699, 3628, 6271, 4993, 2277]","[1983, 1614, 2181, 4147, 1836, 0]",rb2505,2025-03-07 14:55:00,9107,3256.0,3252.0,3257.0,3252.0,32682,0,
"['3251.0', '3252.0', '3253.0', '3254.0', '3255.0', '3256.0', '3257.0']","[0, 5347, 2037, 4834, 4208, 4268, 545]","[4087, 2584, 4361, 6269, 4502, 2544, 0]",rb2505,2025-03-07 15:00:00,-3108,3252.0,3256.0,3257.0,3251.0,45586,0,
1 price Ask Bid symbol datetime delta close open high low volume dj
2 ['3273.0', '3274.0', '3275.0', '3276.0'] [0, 2239, 2381, 3] [864, 1357, 206, 0] rb2505 2025-03-06 21:35:00 2196 3275.0 3275.0 3276.0 3273.0 7050 0
3 ['3271.0', '3272.0', '3273.0', '3274.0', '3275.0', '3276.0'] [0, 604, 1068, 2615, 2480, 433] [1145, 5423, 3975, 2348, 312, 0] rb2505 2025-03-06 21:40:00 -6003 3272.0 3275.0 3276.0 3271.0 20442 0
4 ['3270.0', '3271.0', '3272.0', '3273.0'] [0, 946, 5050, 905] [1459, 4097, 1983, 0] rb2505 2025-03-06 21:45:00 -638 3273.0 3271.0 3273.0 3270.0 14440 0
5 ['3271.0', '3272.0', '3273.0', '3274.0'] [0, 3303, 1202, 116] [2189, 1249, 804, 0] rb2505 2025-03-06 21:50:00 379 3271.0 3272.0 3274.0 3271.0 8863 0
6 ['3271.0', '3272.0', '3273.0'] [0, 1259, 960] [118, 1545, 0] rb2505 2025-03-06 21:55:00 556 3271.0 3272.0 3273.0 3271.0 3882 0
7 ['3270.0', '3271.0', '3272.0', '3273.0'] [0, 2564, 2309, 360] [1248, 2593, 366, 0] rb2505 2025-03-06 22:00:00 1026 3271.0 3272.0 3273.0 3270.0 9440 0
8 ['3270.0', '3271.0', '3272.0', '3273.0', '3274.0', '3275.0', '3276.0'] [0, 1290, 703, 1821, 1779, 2845, 3380] [248, 659, 459, 297, 539, 1570, 0] rb2505 2025-03-06 22:05:00 8046 3276.0 3272.0 3276.0 3270.0 15590 1
9 ['3272.0', '3273.0', '3274.0', '3275.0', '3276.0'] [0, 1190, 1918, 1595, 813] [323, 1601, 1433, 1138, 0] rb2505 2025-03-06 22:10:00 1021 3274.0 3276.0 3276.0 3272.0 10011 0
10 ['3274.0', '3275.0', '3276.0'] [0, 3033, 117] [858, 534, 0] rb2505 2025-03-06 22:15:00 1758 3275.0 3275.0 3276.0 3274.0 4542 0
11 ['3272.0', '3273.0', '3274.0', '3275.0', '3276.0', '3277.0'] [0, 226, 1038, 1347, 3527, 1104] [216, 1675, 1744, 2605, 759, 0] rb2505 2025-03-06 22:20:00 243 3273.0 3274.0 3277.0 3272.0 14244 0
12 ['3272.0', '3273.0', '3274.0', '3275.0'] [0, 1631, 2274, 516] [140, 1621, 455, 0] rb2505 2025-03-06 22:25:00 2205 3274.0 3272.0 3275.0 3272.0 6637 0
13 ['3273.0', '3274.0', '3275.0', '3276.0'] [0, 223, 1897, 739] [86, 1447, 687, 0] rb2505 2025-03-06 22:30:00 639 3274.0 3275.0 3276.0 3273.0 5082 0
14 ['3271.0', '3272.0', '3273.0', '3274.0', '3275.0'] [0, 1111, 1004, 2859, 819] [1924, 2892, 2861, 708, 0] rb2505 2025-03-06 22:35:00 -2592 3274.0 3274.0 3275.0 3271.0 14482 0
15 ['3273.0', '3274.0', '3275.0', '3276.0'] [0, 1193, 3446, 1192] [789, 1104, 2067, 0] rb2505 2025-03-06 22:40:00 1871 3275.0 3274.0 3276.0 3273.0 9926 0
16 ['3274.0', '3275.0', '3276.0', '3277.0', '3278.0', '3279.0', '3280.0', '3281.0'] [0, 318, 2476, 1497, 1682, 3067, 7647, 2494] [384, 524, 628, 2839, 2262, 4056, 4185, 531] rb2505 2025-03-06 22:45:00 3772 3279.0 3275.0 3281.0 3274.0 34604 0
17 ['3278.0', '3279.0', '3280.0', '3281.0', '3282.0'] [0, 1094, 5316, 2515, 3976] [115, 3989, 3361, 3413, 1399] rb2505 2025-03-06 22:50:00 624 3281.0 3279.0 3282.0 3278.0 25218 0
18 ['3277.0', '3278.0', '3279.0', '3280.0', '3281.0', '3282.0', '3283.0'] [0, 208, 149, 1022, 935, 5026, 568] [370, 1888, 2324, 2745, 3584, 3634, 0] rb2505 2025-03-06 22:55:00 -6637 3277.0 3282.0 3283.0 3277.0 22560 0
19 ['3277.0', '3278.0', '3279.0', '3280.0', '3281.0', '3282.0', '3283.0'] [0, 208, 149, 1022, 935, 5026, 568] [370, 1888, 2324, 2745, 3584, 3634, 0] rb2505 2025-03-06 22:55:00 -6637 3277.0 3282.0 3283.0 3277.0 22560 0
20 ['3276.0'] [407] [0] rb2505 2025-03-07 09:00:00 407 3276.0 3276.0 3276.0 3276.0 407 0
21 ['3263.0', '3264.0', '3265.0', '3266.0', '3267.0', '3268.0', '3269.0', '3270.0', '3271.0', '3272.0', '3273.0', '3274.0', '3275.0', '3276.0'] [0, 1185, 3264, 15510, 11309, 3093, 0, 0, 1860, 1562, 6083, 2622, 942, 224] [415, 3808, 8500, 8651, 3437, 3420, 608, 3000, 1967, 2577, 5311, 943, 2063, 0] rb2505 2025-03-07 09:05:00 2954 3266.0 3275.0 3276.0 3263.0 92524 0
22 ['3252.0', '3253.0', '3254.0', '3255.0', '3256.0', '3257.0', '3258.0', '3259.0', '3260.0', '3261.0', '3262.0', '3263.0', '3264.0', '3265.0', '3266.0'] [5660, 5800, 8226, 3436, 6257, 19832, 16459, 2413, 2335, 0, 2177, 0, 768, 2194, 189] [8407, 11202, 4431, 5969, 12929, 20176, 4761, 0, 9168, 1317, 4351, 2172, 682, 1041, 141] rb2505 2025-03-07 09:10:00 -11001 3259.0 3266.0 3266.0 3252.0 163379 0
23 ['3253.0', '3254.0', '3255.0', '3256.0', '3257.0', '3258.0', '3259.0'] [0, 1525, 2917, 5943, 8725, 5876, 157] [1649, 3127, 4842, 6053, 8467, 1043, 0] rb2505 2025-03-07 09:15:00 -38 3254.0 3258.0 3259.0 3253.0 50407 0
24 ['3252.0', '3253.0', '3254.0', '3255.0', '3256.0', '3257.0', '3258.0', '3259.0'] [0, 1824, 3433, 825, 3263, 7570, 5900, 18] [1528, 3068, 2182, 1690, 5805, 3707, 501, 0] rb2505 2025-03-07 09:20:00 4352 3256.0 3254.0 3259.0 3252.0 41356 0
25 ['3256.0', '3257.0', '3258.0', '3259.0', '3260.0', '3261.0', '3262.0'] [0, 1921, 4547, 2302, 3176, 5154, 2122] [282, 2210, 1230, 1385, 4793, 1117, 0] rb2505 2025-03-07 09:25:00 8205 3258.0 3256.0 3262.0 3256.0 30239 0
26 ['3256.0', '3257.0', '3258.0', '3259.0', '3260.0'] [0, 2862, 2588, 2606, 63] [2749, 5408, 4231, 767, 0] rb2505 2025-03-07 09:30:00 -5036 3256.0 3259.0 3260.0 3256.0 21276 0
27 ['3246.0', '3247.0', '3248.0', '3249.0', '3250.0', '3251.0', '3252.0', '3253.0', '3254.0', '3255.0', '3256.0', '3257.0'] [0, 4012, 6866, 9685, 7482, 3317, 2895, 3629, 7328, 2446, 3714, 1341] [9209, 2310, 3079, 13939, 20493, 6274, 8208, 7267, 4002, 6069, 1820, 198] rb2505 2025-03-07 09:35:00 -30153 3253.0 3256.0 3257.0 3246.0 136346 0
28 ['3249.0', '3250.0', '3251.0', '3252.0', '3253.0', '3254.0', '3255.0'] [0, 1527, 7507, 2050, 6828, 3843, 806] [389, 4946, 1997, 3250, 4207, 1199, 0] rb2505 2025-03-07 09:40:00 6573 3253.0 3254.0 3255.0 3249.0 38549 0
29 ['3252.0', '3253.0', '3254.0', '3255.0', '3256.0', '3257.0', '3258.0'] [0, 288, 5527, 3198, 3360, 3196, 2983] [58, 860, 2514, 1333, 1923, 1216, 0] rb2505 2025-03-07 09:45:00 10648 3255.0 3254.0 3258.0 3252.0 26456 0
30 ['3253.0', '3254.0', '3255.0', '3256.0', '3257.0'] [0, 1155, 472, 4032, 913] [399, 1245, 2938, 1161, 0] rb2505 2025-03-07 09:50:00 829 3254.0 3255.0 3257.0 3253.0 12315 0
31 ['3253.0', '3254.0', '3255.0', '3256.0', '3257.0', '3258.0', '3259.0'] [0, 2028, 1383, 1459, 1493, 2308, 736] [954, 2568, 1343, 1502, 1324, 463, 0] rb2505 2025-03-07 09:55:00 1253 3256.0 3255.0 3259.0 3253.0 17587 0
32 ['3254.0', '3255.0', '3256.0', '3257.0', '3258.0', '3259.0'] [0, 885, 3178, 4388, 2676, 1129] [212, 1329, 2996, 1018, 426, 0] rb2505 2025-03-07 10:00:00 6275 3258.0 3255.0 3259.0 3254.0 18248 0
33 ['3256.0', '3257.0', '3258.0', '3259.0', '3260.0'] [0, 2494, 3952, 2746, 1279] [149, 3988, 3446, 2968, 0] rb2505 2025-03-07 10:05:00 -80 3258.0 3258.0 3260.0 3256.0 21022 0
34 ['3258.0', '3259.0', '3260.0', '3261.0', '3262.0'] [0, 957, 2858, 7038, 945] [175, 1080, 3083, 2800, 0] rb2505 2025-03-07 10:10:00 4660 3260.0 3258.0 3262.0 3258.0 18936 0
35 ['3260.0', '3261.0', '3262.0', '3263.0', '3264.0', '3265.0', '3266.0', '3267.0', '3268.0'] [0, 1637, 1567, 6549, 4536, 1818, 6907, 4993, 4233] [190, 854, 2038, 4706, 1553, 3127, 5673, 3900, 0] rb2505 2025-03-07 10:15:00 10199 3265.0 3260.0 3268.0 3260.0 54287 0
36 ['3266.0'] [80] [0] rb2505 2025-03-07 10:20:00 80 3266.0 3266.0 3266.0 3266.0 80 0
37 ['3261.0', '3262.0', '3263.0', '3264.0', '3265.0', '3266.0', '3267.0', '3268.0'] [0, 780, 3409, 1133, 2672, 1964, 2461, 779] [212, 4376, 4176, 2743, 1521, 3407, 1804, 0] rb2505 2025-03-07 10:35:00 -5041 3265.0 3266.0 3268.0 3261.0 31437 0
38 ['3264.0', '3265.0', '3266.0', '3267.0', '3268.0', '3269.0', '3270.0', '3271.0', '3272.0', '3273.0'] [0, 353, 2722, 1474, 2631, 1435, 3091, 1513, 8997, 4883] [132, 3627, 180, 0, 1526, 463, 2403, 6281, 8793, 897] rb2505 2025-03-07 10:40:00 2797 3271.0 3266.0 3273.0 3264.0 51412 0
39 ['3269.0', '3270.0', '3271.0', '3272.0', '3273.0', '3274.0', '3275.0'] [0, 1407, 3234, 4325, 2557, 895, 231] [2051, 5992, 6301, 1713, 3361, 2545, 0] rb2505 2025-03-07 10:45:00 -9314 3271.0 3271.0 3275.0 3269.0 34612 0
40 ['3269.0', '3270.0', '3271.0', '3272.0'] [0, 2542, 2300, 2387] [2024, 5753, 1855, 971] rb2505 2025-03-07 10:50:00 -3374 3272.0 3272.0 3272.0 3269.0 17842 0
41 ['3269.0', '3270.0', '3271.0', '3272.0', '3273.0', '3274.0', '3275.0', '3276.0', '3277.0', '3278.0', '3279.0'] [0, 1114, 716, 2953, 3012, 4006, 2649, 2924, 4621, 10292, 750] [924, 2021, 2976, 4291, 3940, 5660, 1563, 4062, 9243, 1988, 0] rb2505 2025-03-07 10:55:00 -3631 3269.0 3271.0 3279.0 3269.0 69827 0
42 ['3267.0', '3268.0', '3269.0', '3270.0', '3271.0', '3272.0'] [0, 1781, 848, 3193, 2616, 797] [1957, 2177, 2377, 3251, 1941, 0] rb2505 2025-03-07 11:00:00 -2468 3270.0 3269.0 3272.0 3267.0 20966 0
43 ['3268.0', '3269.0', '3270.0', '3271.0', '3272.0', '3273.0'] [0, 409, 1135, 1658, 2417, 519] [917, 1532, 1375, 2421, 688, 0] rb2505 2025-03-07 11:05:00 -795 3273.0 3270.0 3273.0 3268.0 13071 0
44 ['3271.0', '3272.0', '3273.0', '3274.0', '3275.0', '3276.0'] [0, 551, 3054, 3865, 2735, 537] [36, 1685, 3103, 1413, 347, 0] rb2505 2025-03-07 11:10:00 4158 3273.0 3273.0 3276.0 3271.0 17326 0
45 ['3269.0', '3270.0', '3271.0', '3272.0', '3273.0', '3274.0'] [0, 1771, 803, 1844, 1191, 2363] [1621, 1721, 1509, 3674, 2024, 58] rb2505 2025-03-07 11:15:00 -2635 3272.0 3273.0 3274.0 3269.0 18617 0
46 ['3268.0', '3269.0', '3270.0', '3271.0', '3272.0', '3273.0', '3274.0'] [0, 101, 1254, 2094, 1226, 804, 832] [266, 2152, 2364, 1824, 1307, 636, 0] rb2505 2025-03-07 11:20:00 -2238 3270.0 3272.0 3274.0 3268.0 14862 0
47 ['3269.0', '3270.0', '3271.0', '3272.0', '3273.0', '3274.0', '3275.0'] [0, 917, 1350, 955, 1510, 1116, 6] [297, 2699, 843, 384, 2169, 3, 0] rb2505 2025-03-07 11:25:00 -541 3275.0 3270.0 3275.0 3269.0 12269 0
48 ['3269.0', '3270.0', '3271.0', '3272.0', '3273.0', '3274.0', '3275.0', '3276.0'] [0, 1615, 1687, 140, 83, 1395, 6826, 869] [1197, 4148, 460, 994, 1727, 2875, 3938, 0] rb2505 2025-03-07 11:30:00 -2724 3270.0 3274.0 3276.0 3269.0 27954 0
49 ['3270.0'] [0] [10] rb2505 2025-03-07 11:35:00 -10 3270.0 3270.0 3270.0 3270.0 10 0
50 ['3268.0', '3269.0', '3270.0', '3271.0', '3272.0'] [0, 1159, 1947, 3762, 661] [585, 2034, 3152, 1615, 0] rb2505 2025-03-07 13:35:00 143 3270.0 3271.0 3272.0 3268.0 15009 0
51 ['3268.0', '3269.0', '3270.0', '3271.0', '3272.0'] [0, 622, 2163, 1037, 33] [221, 3960, 2227, 370, 0] rb2505 2025-03-07 13:40:00 -2923 3269.0 3270.0 3272.0 3268.0 10707 0
52 ['3264.0', '3265.0', '3266.0', '3267.0', '3268.0', '3269.0', '3270.0'] [0, 1124, 1753, 879, 377, 545, 374] [158, 5009, 5001, 1935, 2505, 908, 0] rb2505 2025-03-07 13:45:00 -10464 3265.0 3270.0 3270.0 3264.0 20568 -1
53 ['3262.0', '3263.0', '3264.0', '3265.0', '3266.0', '3267.0'] [0, 1034, 4315, 2155, 5044, 1230] [215, 5254, 4737, 2809, 1692, 0] rb2505 2025-03-07 13:50:00 -929 3265.0 3265.0 3267.0 3262.0 28559 0
54 ['3264.0', '3265.0', '3266.0', '3267.0', '3268.0', '3269.0', '3270.0'] [0, 1023, 1290, 2347, 821, 1827, 803] [678, 1615, 1438, 432, 948, 36, 0] rb2505 2025-03-07 13:55:00 2964 3266.0 3265.0 3270.0 3264.0 13260 0
55 ['3266.0', '3267.0', '3268.0', '3269.0'] [154, 1705, 3083, 316] [1531, 1207, 1310, 0] rb2505 2025-03-07 14:00:00 1210 3267.0 3267.0 3269.0 3266.0 9339 0
56 ['3256.0', '3257.0', '3258.0', '3259.0', '3260.0', '3261.0', '3262.0', '3263.0', '3264.0', '3265.0', '3266.0', '3267.0', '3268.0'] [0, 113, 412, 1536, 3195, 2820, 1223, 832, 1702, 1186, 1123, 180, 174] [803, 3040, 1559, 1627, 3980, 3301, 899, 2599, 1468, 1453, 953, 111, 0] rb2505 2025-03-07 14:05:00 -7297 3257.0 3267.0 3268.0 3256.0 36296 0
57 ['3255.0', '3256.0', '3257.0', '3258.0', '3259.0', '3260.0'] [0, 7142, 12293, 8720, 2949, 555] [3759, 7656, 9203, 2642, 827, 0] rb2505 2025-03-07 14:10:00 7572 3258.0 3257.0 3260.0 3255.0 55762 0
58 ['3255.0', '3256.0', '3257.0', '3258.0', '3259.0'] [0, 3358, 4138, 4316, 546] [1611, 5572, 1726, 2036, 0] rb2505 2025-03-07 14:15:00 1413 3256.0 3257.0 3259.0 3255.0 23303 0
59 ['3254.0', '3255.0', '3256.0', '3257.0', '3258.0'] [0, 1270, 3528, 7590, 1545] [2890, 6003, 4361, 2136, 0] rb2505 2025-03-07 14:20:00 -1457 3257.0 3255.0 3258.0 3254.0 29323 0
60 ['3256.0', '3257.0', '3258.0', '3259.0', '3260.0', '3261.0', '3262.0', '3263.0', '3264.0', '3265.0', '3266.0'] [0, 739, 1330, 941, 2998, 4917, 2955, 3201, 3964, 2103, 1628] [318, 608, 52, 423, 1073, 611, 1765, 3611, 1504, 1623, 0] rb2505 2025-03-07 14:25:00 13188 3264.0 3257.0 3266.0 3256.0 36540 2
61 ['3259.0', '3260.0', '3261.0', '3262.0', '3263.0', '3264.0'] [0, 911, 3423, 2691, 350, 162] [242, 3816, 1896, 2484, 1170, 0] rb2505 2025-03-07 14:30:00 -2071 3260.0 3263.0 3264.0 3259.0 17145 0
62 ['3255.0', '3256.0', '3257.0', '3258.0', '3259.0', '3260.0', '3261.0', '3262.0', '3263.0'] [0, 915, 2797, 849, 610, 53, 953, 1753, 828] [909, 2863, 1997, 1745, 1111, 1214, 674, 1365, 0] rb2505 2025-03-07 14:35:00 -3120 3256.0 3261.0 3263.0 3255.0 20636 0
63 ['3255.0', '3256.0', '3257.0', '3258.0', '3259.0'] [0, 2133, 2113, 3459, 55] [618, 1256, 2243, 629, 0] rb2505 2025-03-07 14:40:00 3014 3256.0 3255.0 3259.0 3255.0 12506 0
64 ['3253.0', '3254.0', '3255.0', '3256.0', '3257.0'] [366, 718, 5841, 7496, 1035] [4146, 7433, 4375, 3639, 0] rb2505 2025-03-07 14:45:00 -4137 3253.0 3256.0 3257.0 3253.0 35049 0
65 ['3251.0', '3252.0', '3253.0', '3254.0', '3255.0', '3256.0'] [0, 10582, 4808, 4494, 724, 996] [8116, 5025, 5497, 986, 121, 0] rb2505 2025-03-07 14:50:00 1859 3252.0 3253.0 3256.0 3251.0 41349 0
66 ['3252.0', '3253.0', '3254.0', '3255.0', '3256.0', '3257.0'] [0, 3699, 3628, 6271, 4993, 2277] [1983, 1614, 2181, 4147, 1836, 0] rb2505 2025-03-07 14:55:00 9107 3256.0 3252.0 3257.0 3252.0 32682 0
67 ['3251.0', '3252.0', '3253.0', '3254.0', '3255.0', '3256.0', '3257.0'] [0, 5347, 2037, 4834, 4208, 4268, 545] [4087, 2584, 4361, 6269, 4502, 2544, 0] rb2505 2025-03-07 15:00:00 -3108 3252.0 3256.0 3257.0 3251.0 45586 0
@@ -0,0 +1,106 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>订单流实时数据监控</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.11.5/css/dataTables.bootstrap5.min.css">
<style>
table {
width: 100%;
border-collapse: collapse;
}
table, th, td {
border: 1px solid black;
}
th, td {
padding: 8px;
text-align: center;
}
button {
margin: 10px;
padding: 10px;
cursor: pointer;
}
</style>
</head>
<body>
<h1>Real-Time CSV Data Viewer</h1>
<!-- 动态生成按钮 -->
{% for file_name, file_path in files.items() %}
<button onclick="loadData('{{ file_name }}')">{{ file_name }}</button>
{% endfor %}
<h3>Data for {{ file_name }}</h3>
<table id="data-table">
<thead>
<tr>
<th>Symbol</th>
<th>Datetime</th>
<th>Delta</th>
<th>Close</th>
<th>Open</th>
<th>High</th>
<th>Low</th>
<th>Volume</th>
<th>DJ</th>
<th>Delta累计</th>
<th>POC</th>
<th>终极平滑值</th>
<th>趋势方向</th>
</tr>
</thead>
<tbody>
{% for row in data %}
<tr>
<td>{{ row.symbol }}</td>
<td>{{ row.datetime }}</td>
<td>{{ row.delta }}</td>
<td>{{ row.close }}</td>
<td>{{ row.open }}</td>
<td>{{ row.high }}</td>
<td>{{ row.low }}</td>
<td>{{ row.volume }}</td>
<td>{{ row.dj }}</td>
<td>{{ row.delta累计 }}</td>
<td>{{ row.POC }}</td>
<td>{{ row.终极平滑值 }}</td>
<td>{{ row.趋势方向 }}</td>
</tr>
{% endfor %}
</tbody>
</table>
<script>
function loadData(fileName) {
fetch('/data/' + fileName)
.then(response => response.json())
.then(data => {
let tableBody = document.querySelector("#data-table tbody");
tableBody.innerHTML = ''; // 清空现有数据行
data.forEach(row => {
let rowElement = document.createElement('tr');
rowElement.innerHTML = `
<td>${row.symbol}</td>
<td>${row.datetime}</td>
<td>${row.delta}</td>
<td>${row.close}</td>
<td>${row.open}</td>
<td>${row.high}</td>
<td>${row.low}</td>
<td>${row.volume}</td>
<td>${row.dj}</td>
<td>${row.delta累计}</td>
<td>${row.POC}</td>
<td>${row.终极平滑值}</td>
<td>${row.趋势方向}</td>
`;
tableBody.appendChild(rowElement);
});
});
}
</script>
</body>
</html>
@@ -0,0 +1,199 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CSV Data Viewer</title>
<style>
table {
width: 100%;
border-collapse: collapse;
}
table, th, td {
border: 1px solid black;
}
th, td {
padding: 8px;
text-align: center;
}
button {
margin: 10px;
padding: 10px;
cursor: pointer;
}
select {
width: 100%;
padding: 5px;
text-align: center;
}
</style>
</head>
<body>
<h1>Real-Time CSV Data Viewer</h1>
<!-- 动态生成文件切换按钮 -->
{% for file_name, file_path in files.items() %}
<button onclick="loadData('{{ file_name }}')">{{ file_name }}</button>
{% endfor %}
<h3>Data for {{ file_name }}</h3>
<table id="data-table">
<thead>
<tr>
<th>
<select id="filter-price" onchange="filterTable()">
<option value="">Price</option>
</select>
</th>
<th>
<select id="filter-Ask" onchange="filterTable()">
<option value="">Ask</option>
</select>
</th>
<th>
<select id="filter-Bid" onchange="filterTable()">
<option value="">Bid</option>
</select>
</th>
<th>
<select id="filter-symbol" onchange="filterTable()">
<option value="">Symbol</option>
</select>
</th>
<th>
<select id="filter-datetime" onchange="filterTable()">
<option value="">Datetime</option>
</select>
</th>
<th>
<select id="filter-delta" onchange="filterTable()">
<option value="">Delta</option>
</select>
</th>
<th>
<select id="filter-close" onchange="filterTable()">
<option value="">Close</option>
</select>
</th>
<th>
<select id="filter-open" onchange="filterTable()">
<option value="">Open</option>
</select>
</th>
<th>
<select id="filter-high" onchange="filterTable()">
<option value="">High</option>
</select>
</th>
<th>
<select id="filter-low" onchange="filterTable()">
<option value="">Low</option>
</select>
</th>
<th>
<select id="filter-volume" onchange="filterTable()">
<option value="">Volume</option>
</select>
</th>
<th>
<select id="filter-dj" onchange="filterTable()">
<option value="">DJ</option>
</select>
</th>
</tr>
</thead>
<tbody>
{% for row in data %}
<tr>
<td>{{ row.price }}</td>
<td>{{ row.Ask }}</td>
<td>{{ row.Bid }}</td>
<td>{{ row.symbol }}</td>
<td>{{ row.datetime }}</td>
<td>{{ row.delta }}</td>
<td>{{ row.close }}</td>
<td>{{ row.open }}</td>
<td>{{ row.high }}</td>
<td>{{ row.low }}</td>
<td>{{ row.volume }}</td>
<td>{{ row.dj }}</td>
</tr>
{% endfor %}
</tbody>
</table>
<script>
function loadData(fileName) {
fetch('/data/' + fileName)
.then(response => response.json())
.then(data => {
let tableBody = document.querySelector("#data-table tbody");
tableBody.innerHTML = ''; // 清空现有数据行
data.forEach(row => {
let rowElement = document.createElement('tr');
rowElement.innerHTML = `
<td>${row.price}</td>
<td>${row.Ask}</td>
<td>${row.Bid}</td>
<td>${row.symbol}</td>
<td>${row.datetime}</td>
<td>${row.delta}</td>
<td>${row.close}</td>
<td>${row.open}</td>
<td>${row.high}</td>
<td>${row.low}</td>
<td>${row.volume}</td>
<td>${row.dj}</td>
`;
tableBody.appendChild(rowElement);
});
populateFilters(data);
});
}
function populateFilters(data) {
let columns = ["price", "Ask", "Bid", "symbol", "datetime", "delta", "close", "open", "high", "low", "volume", "dj"];
columns.forEach(col => {
let uniqueValues = [...new Set(data.map(row => row[col]))];
let select = document.getElementById(`filter-${col}`);
select.innerHTML = '<option value="">All</option>';
uniqueValues.forEach(value => {
select.innerHTML += `<option value="${value}">${value}</option>`;
});
});
}
function filterTable() {
let filters = {
price: document.getElementById("filter-price").value,
Ask: document.getElementById("filter-Ask").value,
Bid: document.getElementById("filter-Bid").value,
symbol: document.getElementById("filter-symbol").value,
datetime: document.getElementById("filter-datetime").value,
delta: document.getElementById("filter-delta").value,
close: document.getElementById("filter-close").value,
open: document.getElementById("filter-open").value,
high: document.getElementById("filter-high").value,
low: document.getElementById("filter-low").value,
volume: document.getElementById("filter-volume").value,
dj: document.getElementById("filter-dj").value
};
let rows = document.querySelectorAll("#data-table tbody tr");
rows.forEach(row => {
let cells = row.children;
let show = true;
Object.keys(filters).forEach((col, index) => {
if (filters[col] && cells[index].textContent !== filters[col]) {
show = false;
}
});
row.style.display = show ? "" : "none";
});
}
</script>
</body>
</html>