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

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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -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

View File

@@ -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 = ["240884432@qq.com"] # 设置邮件接收人地址
subject = "TD_Simnow_Signal" # 设置邮件主题 订单流策略交易信号
# 配置邮件服务器信息
smtp_server = "smtp.qq.com" # 设置发送邮件的 SMTP 服务器地址
smtp_port = 465 # 设置发送邮件的 SMTP 服务器端口号,一般为 25 端口 465
sender = "240884432@qq.com" # 设置发送邮件的邮箱地址
username = "240884432@qq.com" # 设置发送邮件的邮箱用户名
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) # 监听所有网络接口

View File

@@ -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 = ["240884432@qq.com"] # 设置邮件接收人地址
subject = "TD_Simnow_Signal" # 设置邮件主题 订单流策略交易信号
# 配置邮件服务器信息
smtp_server = "smtp.qq.com" # 设置发送邮件的 SMTP 服务器地址
smtp_port = 465 # 设置发送邮件的 SMTP 服务器端口号,一般为 25 端口 465
sender = "240884432@qq.com" # 设置发送邮件的邮箱地址
username = "240884432@qq.com" # 设置发送邮件的邮箱用户名
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) # 监听所有网络接口

View File

@@ -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 = ["240884432@qq.com"] # 设置邮件接收人地址
subject = "TD_Simnow_Signal" # 设置邮件主题 订单流策略交易信号
# 配置邮件服务器信息
smtp_server = "smtp.qq.com" # 设置发送邮件的 SMTP 服务器地址
smtp_port = 465 # 设置发送邮件的 SMTP 服务器端口号,一般为 25 端口 465
sender = "240884432@qq.com" # 设置发送邮件的邮箱地址
username = "240884432@qq.com" # 设置发送邮件的邮箱用户名
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) # 监听所有网络接口

View File

@@ -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 = ["240884432@qq.com"] # 设置邮件接收人地址
subject = "TD_Simnow_Signal" # 设置邮件主题 订单流策略交易信号
# 配置邮件服务器信息
smtp_server = "smtp.qq.com" # 设置发送邮件的 SMTP 服务器地址
smtp_port = 465 # 设置发送邮件的 SMTP 服务器端口号,一般为 25 端口 465
sender = "240884432@qq.com" # 设置发送邮件的邮箱地址
username = "240884432@qq.com" # 设置发送邮件的邮箱用户名
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) # 监听所有网络接口

View File

@@ -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 = ["240884432@qq.com"] # 设置邮件接收人地址
subject = "TD_Simnow_Signal" # 设置邮件主题 订单流策略交易信号
# 配置邮件服务器信息
smtp_server = "smtp.qq.com" # 设置发送邮件的 SMTP 服务器地址
smtp_port = 465 # 设置发送邮件的 SMTP 服务器端口号,一般为 25 端口 465
sender = "240884432@qq.com" # 设置发送邮件的邮箱地址
username = "240884432@qq.com" # 设置发送邮件的邮箱用户名
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) # 监听所有网络接口

View File

@@ -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) # 监听所有网络接口

View File

@@ -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 = ["240884432@qq.com"] # 设置邮件接收人地址
subject = "TD_Simnow_Signal" # 设置邮件主题 订单流策略交易信号
# 配置邮件服务器信息
smtp_server = "smtp.qq.com" # 设置发送邮件的 SMTP 服务器地址
smtp_port = 465 # 设置发送邮件的 SMTP 服务器端口号,一般为 25 端口 465
sender = "240884432@qq.com" # 设置发送邮件的邮箱地址
username = "240884432@qq.com" # 设置发送邮件的邮箱用户名
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) # 监听所有网络接口

View File

@@ -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 = ["240884432@qq.com"] # 设置邮件接收人地址
subject = "TD_Simnow_Signal" # 设置邮件主题 订单流策略交易信号
# 配置邮件服务器信息
smtp_server = "smtp.qq.com" # 设置发送邮件的 SMTP 服务器地址
smtp_port = 465 # 设置发送邮件的 SMTP 服务器端口号,一般为 25 端口 465
sender = "240884432@qq.com" # 设置发送邮件的邮箱地址
username = "240884432@qq.com" # 设置发送邮件的邮箱用户名
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) # 监听所有网络接口

View File

@@ -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

View File

@@ -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/bootstrap@5.1.3/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>

View File

@@ -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>