#集合竞价主力试盘都有哪些手法##股票财经##量化#

策略直接输出三种结论:出货试盘、拉升试盘或无试盘。
代码基于XTP接口实现,包含了详细的注释。
#include <iostream>
#include <vector>
#include <deque>
#include <unordered_map>
#include <cmath>
#include <algorithm>
#include <chrono>
#include <xtp_api_struct.h>
#include <xtp_quote_api.h>
// 命名空间简化
using namespace std;
using namespace std::chrono;
// 常量定义
const double PRICE_CHANGE_THRESHOLD = 0.015; // 1.5%价格变动阈值
const double VOLUME_RATIO_THRESHOLD = 3.0; // 成交量比率阈值
const double RECOVERY_THRESHOLD = 0.7; // 价格恢复阈值
const double SHADOW_RATIO_THRESHOLD = 0.3; // 影线比例阈值
const int TIME_WINDOW_SECONDS = 30; // 分析时间窗口(秒)
const int VOLUME_ANALYSIS_WINDOW = 10; // 成交量分析窗口(数据点)
const double TEST_PROBABILITY_THRESHOLD = 0.65; // 试盘概率阈值
// 试盘类型枚举
enum TestType {
NO_TEST, // 无试盘
UPWARD_TEST, // 拉升试盘
DOWNWARD_TEST, // 出货试盘
AMBIGUOUS_TEST // 模棱两可的情况
};
// 股票数据结构
struct StockData {
string ticker; // 股票代码
double last_price; // 最新价格
double pre_close; // 前收盘价
double bid_prices[5]; // 买1-买5价格
double ask_prices[5]; // 卖1-卖5价格
int64_t bid_volumes[5]; // 买1-买5量
int64_t ask_volumes[5]; // 卖1-卖5量
int64_t volume; // 成交量
int64_t turnover; // 成交额
high_resolution_clock::time_point timestamp; // 时间戳
// 存储历史K线数据用于分析
deque<double> price_history; // 价格历史
deque<int64_t> volume_history; // 成交量历史
deque<double> price_changes; // 价格变动历史
};
// 试盘检测结果
struct TestDetectionResult {
TestType test_type = NO_TEST; // 试盘类型
double upward_prob = 0.0; // 拉升试盘概率
double downward_prob = 0.0; // 出货试盘概率
vector<string> indicators; // 触发的指标
};
// 市场数据分析器
class MarketAnalyzer {
private:
// 存储股票数据
unordered_map<string, StockData> stock_map;
// 检测挂单异常
void detectOrderAbnormalities(const StockData& data, TestDetectionResult& result) {
// 检查大托单(一般出目前出货试盘)
if (data.bid_volumes[0] > 5 * data.bid_volumes[1] &&
data.bid_volumes[0] > 1000000) { // 假设100万股为大单
result.indicators.push_back("BIG_BID_ORDER");
result.downward_prob += 0.15; // 出货试盘特征
}
// 检查大压单(一般出目前拉升试盘)
if (data.ask_volumes[0] > 5 * data.ask_volumes[1] &&
data.ask_volumes[0] > 1000000) {
result.indicators.push_back("BIG_ASK_ORDER");
result.upward_prob += 0.15; // 拉升试盘特征
}
// 检查夹板单(可能出目前两种试盘中)
if (data.bid_volumes[2] > 500000 && data.ask_volumes[2] > 500000 &&
(data.ask_prices[2] - data.bid_prices[2]) < (0.005 * data.last_price)) {
result.indicators.push_back("SANDWICH_ORDER");
// 夹板单本身不直接表明方向,但增加整体试盘概率
result.upward_prob += 0.05;
result.downward_prob += 0.05;
}
}
// 检测价格异动
void detectPriceAnomalies(const string& ticker, TestDetectionResult& result) {
if (stock_map.find(ticker) == stock_map.end() ||
stock_map[ticker].price_history.size() < VOLUME_ANALYSIS_WINDOW) {
return;
}
const auto& data = stock_map[ticker];
const auto& prices = data.price_history;
// 计算价格波动范围
double max_price = *max_element(prices.begin(), prices.end());
double min_price = *min_element(prices.begin(), prices.end());
double price_range = max_price - min_price;
// 检测长上影线(出货试盘特征)
if (max_price > data.last_price) {
double upper_shadow = max_price - data.last_price;
if (upper_shadow > SHADOW_RATIO_THRESHOLD * price_range) {
result.indicators.push_back("UPPER_SHADOW");
result.downward_prob += 0.25; // 出货试盘特征
}
}
// 检测长下影线(拉升试盘特征)
if (min_price < data.last_price) {
double lower_shadow = data.last_price - min_price;
if (lower_shadow > SHADOW_RATIO_THRESHOLD * price_range) {
result.indicators.push_back("LOWER_SHADOW");
result.upward_prob += 0.25; // 拉升试盘特征
}
}
// 检测快速拉升(拉升试盘特征)
// 检测快速打压(出货试盘特征)
double max_up_change = 0.0;
double max_down_change = 0.0;
for (size_t i = 1; i < prices.size(); ++i) {
double change = (prices[i] - prices[i-1]) / prices[i-1];
if (change > max_up_change) {
max_up_change = change;
}
if (change < max_down_change) {
max_down_change = change;
}
}
// 快速拉升特征
if (max_up_change > PRICE_CHANGE_THRESHOLD) {
result.indicators.push_back("RAPID_UP_PRICE_CHANGE");
result.upward_prob += 0.3;
}
// 快速打压特征
if (abs(max_down_change) > PRICE_CHANGE_THRESHOLD) {
result.indicators.push_back("RAPID_DOWN_PRICE_CHANGE");
result.downward_prob += 0.3;
}
}
// 检测成交量异常
void detectVolumeAnomalies(const string& ticker, TestDetectionResult& result) {
if (stock_map.find(ticker) == stock_map.end() ||
stock_map[ticker].volume_history.size() < VOLUME_ANALYSIS_WINDOW) {
return;
}
const auto& data = stock_map[ticker];
const auto& volumes = data.volume_history;
int64_t current_volume = volumes.back();
// 计算平均成交量
int64_t sum_volume = 0;
for (int i = 0; i < volumes.size() - 1; ++i) {
sum_volume += volumes[i];
}
double avg_volume = static_cast<double>(sum_volume) / (volumes.size() - 1);
// 检测成交量突增(可能出目前两种试盘中)
if (avg_volume > 0 && current_volume > VOLUME_RATIO_THRESHOLD * avg_volume) {
result.indicators.push_back("VOLUME_SPIKE");
// 结合价格方向判断试盘类型
if (!data.price_changes.empty()) {
double last_price_change = data.price_changes.back();
if (last_price_change > 0) {
result.upward_prob += 0.2; // 价量齐升 - 拉升试盘
} else if (last_price_change < 0) {
result.downward_prob += 0.2; // 价跌量增 - 出货试盘
} else {
// 量增价平 - 两种可能性都有
result.upward_prob += 0.1;
result.downward_prob += 0.1;
}
}
}
// 检测脉冲式成交量(快速试盘的典型特征)
if (volumes.size() >= 3) {
int64_t prev_volume = volumes[volumes.size()-2];
int64_t prev_prev_volume = volumes[volumes.size()-3];
if (current_volume > 4 * prev_volume &&
prev_prev_volume > 0.8 * prev_volume) {
result.indicators.push_back("VOLUME_PULSE");
// 脉冲式成交量增加整体试盘概率
result.upward_prob += 0.15;
result.downward_prob += 0.15;
}
}
}
// 检测价格恢复情况
void detectPriceRecovery(const string& ticker, TestDetectionResult& result) {
if (stock_map.find(ticker) == stock_map.end() ||
stock_map[ticker].price_history.size() < 5) {
return;
}
const auto& data = stock_map[ticker];
const auto& prices = data.price_history;
size_t n = prices.size();
// 检测拉升后的价格回落(出货试盘特征)
if (prices[n-3] < prices[n-2] && prices[n-2] > prices[n-1]) {
double recovery_ratio = (prices[n-2] - prices[n-1]) / (prices[n-2] - prices[n-3]);
if (recovery_ratio > RECOVERY_THRESHOLD) {
result.indicators.push_back("UP_PRICE_RECOVERY");
result.downward_prob += 0.2; // 快速回落表明上方压力大,可能是出货试盘
}
}
// 检测打压后的价格回升(拉升试盘特征)
if (prices[n-3] > prices[n-2] && prices[n-2] < prices[n-1]) {
double recovery_ratio = (prices[n-1] - prices[n-2]) / (prices[n-3] - prices[n-2]);
if (recovery_ratio > RECOVERY_THRESHOLD) {
result.indicators.push_back("DOWN_PRICE_RECOVERY");
result.upward_prob += 0.2; // 快速回升表明下方支撑强,可能是拉升试盘
}
}
}
public:
// 更新市场数据
void updateMarketData(const XTPMD* market_data) {
string ticker(market_data->ticker);
// 初始化或更新股票数据
if (stock_map.find(ticker) == stock_map.end()) {
stock_map[ticker] = StockData();
stock_map[ticker].ticker = ticker;
}
auto& data = stock_map[ticker];
double prev_price = data.last_price;
data.last_price = market_data->last_price;
data.pre_close = market_data->pre_close_price;
data.volume = market_data->qty;
data.turnover = market_data->turnover;
data.timestamp = high_resolution_clock::now();
// 计算价格变动
if (prev_price > 0) {
double price_change = (data.last_price - prev_price) / prev_price;
data.price_changes.push_back(price_change);
if (data.price_changes.size() > VOLUME_ANALYSIS_WINDOW) {
data.price_changes.pop_front();
}
}
// 更新买卖盘口
for (int i = 0; i < 5; ++i) {
data.bid_prices[i] = market_data->bid[i];
data.ask_prices[i] = market_data->ask[i];
data.bid_volumes[i] = market_data->bid_qty[i];
data.ask_volumes[i] = market_data->ask_qty[i];
}
// 更新价格和成交量历史
data.price_history.push_back(data.last_price);
data.volume_history.push_back(data.volume);
// 保持历史数据在窗口大小内
if (data.price_history.size() > VOLUME_ANALYSIS_WINDOW) {
data.price_history.pop_front();
}
if (data.volume_history.size() > VOLUME_ANALYSIS_WINDOW) {
data.volume_history.pop_front();
}
}
// 检测试盘行为
TestDetectionResult detectTestPattern(const string& ticker) {
TestDetectionResult result;
if (stock_map.find(ticker) == stock_map.end()) {
return result;
}
const auto& data = stock_map[ticker];
// 1. 检测挂单异常
detectOrderAbnormalities(data, result);
// 2. 检测价格异动
detectPriceAnomalies(ticker, result);
// 3. 检测成交量异常
detectVolumeAnomalies(ticker, result);
// 4. 检测价格恢复情况
detectPriceRecovery(ticker, result);
// 5. 确定试盘类型
double max_prob = max(result.upward_prob, result.downward_prob);
if (max_prob < TEST_PROBABILITY_THRESHOLD) {
result.test_type = NO_TEST;
} else {
if (result.upward_prob > result.downward_prob) {
result.test_type = UPWARD_TEST;
} else if (result.downward_prob > result.upward_prob) {
result.test_type = DOWNWARD_TEST;
} else {
result.test_type = AMBIGUOUS_TEST;
}
}
// 概率上限为1.0
result.upward_prob = min(result.upward_prob, 1.0);
result.downward_prob = min(result.downward_prob, 1.0);
return result;
}
// 清理过期数据
void cleanExpiredData() {
auto now = high_resolution_clock::now();
for (auto it = stock_map.begin(); it != stock_map.end(); ) {
auto duration = duration_cast<seconds>(now - it->second.timestamp);
if (duration.count() > TIME_WINDOW_SECONDS * 2) {
it = stock_map.erase(it);
} else {
++it;
}
}
}
};
// XTP行情回调处理类
class QuoteSpi : public XTP::API::QuoteSpi {
private:
MarketAnalyzer analyzer;
// 将TestType转换为字符串
string testTypeToString(TestType type) {
switch(type) {
case NO_TEST: return "无试盘";
case UPWARD_TEST: return "拉升试盘";
case DOWNWARD_TEST: return "出货试盘";
case AMBIGUOUS_TEST: return "模棱两可";
default: return "未知";
}
}
public:
// 深度行情通知
virtual void OnDepthMarketData(XTPMD *market_data, int64_t bid1_qty[], int32_t bid1_count, int32_t max_bid1_count,
int64_t ask1_qty[], int32_t ask1_count, int32_t max_ask1_count) {
// 更新市场数据
analyzer.updateMarketData(market_data);
// 检测试盘模式
string ticker(market_data->ticker);
TestDetectionResult result = analyzer.detectTestPattern(ticker);
// 输出检测结果
if (result.test_type != NO_TEST) {
cout << "
[试盘检测] " << ticker
<< " | 类型: " << testTypeToString(result.test_type)
<< " | 拉升概率: " << result.upward_prob * 100 << "%"
<< " | 出货概率: " << result.downward_prob * 100 << "%"
<< " | 指标: ";
for (const auto& ind : result.indicators) {
cout << ind << " ";
}
cout << endl;
// 根据试盘类型采取不同策略
switch(result.test_type) {
case UPWARD_TEST:
// 拉升试盘 - 思考逢低买入
cout << " 策略提议: 关注回踩机会,设置买入条件单" << endl;
break;
case DOWNWARD_TEST:
// 出货试盘 - 思考逢高卖出
cout << " 策略提议: 警惕上方压力,设置止盈止损" << endl;
break;
case AMBIGUOUS_TEST:
// 模棱两可 - 保持观望
cout << " 策略提议: 保持观望,等待更多信号" << endl;
break;
default:
break;
}
}
}
// 其他回调方法
virtual void OnSubscribeAllMarketData(XTP_EXCHANGE_TYPE exchange_id, XTPRI *error_info) {}
virtual void OnUnSubscribeAllMarketData(XTP_EXCHANGE_TYPE exchange_id, XTPRI *error_info) {}
virtual void OnQueryAllTickersFullInfo(XTPQFI* ticker_info, XTPRI *error_info, bool is_last) {}
};
// 主函数
int main() {
// 创建行情API实例
XTP::API::QuoteApi* quote_api = XTP::API::QuoteApi::CreateQuoteApi("client_id", "./log/");
if (!quote_api) {
cerr << "创建行情API实例失败" << endl;
return 1;
}
// 创建回调处理实例
QuoteSpi quote_spi;
quote_api->RegisterSpi("e_spi);
// 登录行情服务器
XTPRI login_result;
const char* ip = "120.27.164.138"; // XTP服务器IP
int port = 6002; // 行情端口
const char* username = "username"; // 替换为实际用户名
const char* password = "password"; // 替换为实际密码
int session_id = quote_api->Login(ip, port, username, password, XTP_PROTOCOL_TCP);
if (session_id == 0 || login_result.error_id != 0) {
cerr << "登录失败: " << login_result.error_msg << endl;
quote_api->Release();
return 1;
}
cout << "登录成功. 会话ID: " << session_id << endl;
// 订阅行情
vector<string> tickers = {"600000", "000001", "600519", "000858"}; // 示例股票代码
vector<XTP_EXCHANGE_TYPE> exchanges = {
XTP_EXCHANGE_SH, // 上证
XTP_EXCHANGE_SZ, // 深证
XTP_EXCHANGE_SH, // 上证
XTP_EXCHANGE_SZ // 深证
};
for (size_t i = 0; i < tickers.size(); ++i) {
int ret = quote_api->SubscribeMarketData(tickers[i].c_str(), exchanges[i]);
if (ret != 0) {
cerr << "订阅 " << tickers[i] << " 失败" << endl;
} else {
cout << "已订阅 " << tickers[i] << endl;
}
}
// 主循环
cout << "
开始监控试盘行为..." << endl;
cout << "----------------------------------------" << endl;
while (true) {
// 定期清理过期数据
quote_spi.cleanExpiredData();
// 休眠一段时间,避免CPU过度占用
this_thread::sleep_for(milliseconds(100));
}
// 清理
quote_api->Logout();
quote_api->Release();
return 0;
}