1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
// DataProcessing.cpp
#include "DataProcessing.h"
#include "Common.h"
#include <cstdio>
#include <cstring>
#include <memory>
#include <iostream>
#include <vector>
#include <algorithm>
/*******************************************************/
extern PDATAIOFUNC g_pFuncCallBack;
LPHISDAT allocateHisDat(short nDataNum) {
return new HISDAT[nDataNum];
}
long fetchHistoricalData(char* Code, short nSetCode, short DataType, LPHISDAT pHisDat, short nDataNum, NTime time1, NTime time2, BYTE nTQ) {
return g_pFuncCallBack(Code, nSetCode, DataType, pHisDat, nDataNum, time1, time2, nTQ, 0);
}
// 计算成交量变化率
std::vector<float> calculateVolumeChangeRate(const HISDAT* pHisDat, long readnum) {
std::vector<float> volumeChangeRate(readnum);
for (long i = 1; i < readnum; ++i) {
float prevVolume = pHisDat[i - 1].fVolume;
volumeChangeRate[i] = (prevVolume != 0) ? ((pHisDat[i].fVolume - prevVolume) / prevVolume) * 100.0f : 0.0f;
}
return volumeChangeRate;
}
// 检测最近N日的下跌趋势
bool hasSignificantDowntrend(const std::vector<float>& prices, int nDays) {
int downDays = 0;
int requiredDownDays = static_cast<int>(nDays * 0.80); // 80%的天数都是下跌趋势
for (int i = prices.size() - nDays; i < prices.size(); ++i) {
if (prices[i] < prices[i - 1]) {
downDays++;
}
}
return downDays >= requiredDownDays;
}
// 检测突然放量
bool isSuddenVolumeIncrease(const std::vector<float>& volumeChangeRate, float threshold) {
return volumeChangeRate.back() > threshold;
}
// 计算枢轴点和支撑位、压力位
void calculatePivotPoints(float high, float low, float close, float& pivot, float& support1, float& support2, float& resistance1, float& resistance2) {
pivot = (high + low + close) / 3.0f;
support1 = (2 * pivot) - high;
support2 = pivot - (high - low);
resistance1 = (2 * pivot) - low;
resistance2 = pivot + (high - low);
}
// 主力潜伏检测函数
bool detectMainForcePresence(const HISDAT* pHisDat, long readnum, const std::vector<float>& prices, int nDays) {
// 检查成交量变化率
std::vector<float> volumeChangeRate = calculateVolumeChangeRate(pHisDat, readnum);
float volumeThreshold = 100.0f; // 设置一个阈值,例如100%
// 检测最近N日的下跌趋势
if (readnum >= nDays && !hasSignificantDowntrend(prices, nDays)) {
return false;
}
// 检测突然放量
return isSuddenVolumeIncrease(volumeChangeRate, volumeThreshold);
}
BOOL processData(char* Code, short nSetCode, int Value[4], short DataType, short nDataNum, NTime time1, NTime time2, BYTE nTQ, unsigned long unused) {
BOOL nRet = FALSE;
std::unique_ptr<HISDAT[]> pHisDat(new HISDAT[nDataNum]);
std::unique_ptr<STOCKINFO> pStockInfo(new STOCKINFO());
static char logMessage[1024] = { 0 };
// 获取股票基本信息
long readnum1 = g_pFuncCallBack(Code, nSetCode, STKINFO_DAT, pStockInfo.get(), 1, time1, time2, 0, 0);
if (readnum1 <= 0 || !pStockInfo) {
return FALSE;
}
// 排除名称中包含 "ST" 的股票
if (strstr(pStockInfo->Name, "ST") != nullptr) {
return FALSE;
}
// 获取历史数据
long readnum = g_pFuncCallBack(Code, nSetCode, DataType, pHisDat.get(), nDataNum, time1, time2, nTQ, 0);
if (readnum <= 0 || pHisDat[readnum - 1].Close == 0) {
return FALSE;
}
// 获取收盘价数据
std::vector<float> prices(readnum);
for (long i = 0; i < readnum; ++i) {
prices[i] = pHisDat[i].Close;
}
// 使用 Value[0] 作为最近N日的交易日
int nDays = Value[0];
// 检测主力潜伏
if (detectMainForcePresence(pHisDat.get(), readnum, prices, nDays)) {
sprintf(logMessage, "[processData] 检测到主力潜伏 股票代码: %s 股票名称: %s", Code, pStockInfo->Name);
LogMessage(logMessage);
nRet = TRUE;
}
// 计算最近一天的高点、低点和收盘价
float high = pHisDat[readnum - 1].High;
float low = pHisDat[readnum - 1].Low;
float close = pHisDat[readnum - 1].Close;
// 计算枢轴点和支撑位、压力位
float pivot, support1, support2, resistance1, resistance2;
calculatePivotPoints(high, low, close, pivot, support1, support2, resistance1, resistance2);
// 记录支撑位和压力位,并包括股票代码和股票名称
sprintf(logMessage, "股票代码: %s 股票名称: %s 支撑位1: %.2f, 支撑位2: %.2f, 压力位1: %.2f, 压力位2: %.2f",
Code, pStockInfo->Name, support1, support2, resistance1, resistance2);
LogMessage(logMessage);
return nRet;
}
|