weighted signal code

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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
//+------------------------------------------------------------------+
//| WeightedSignal.mqh |
//| Copyright 2000-2025, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#include <Expert\ExpertSignal.mqh>

//+------------------------------------------------------------------+
//| Class: CWeightedSignal |
//| Purpose: Implements a trading signal based on weighted |
//| indicators. Each signal source has an associated |
//| weight, influencing the final signal calculation. |
//+------------------------------------------------------------------+
class CWeightedSignal : public CExpertSignal
{
protected:
struct SignalSource
{
string name; // Name of the signal source
double weight; // Weight of the signal
};

// List of signal sources stored as objects in an array
CArrayObj *m_signal_sources;

public:
CWeightedSignal(void); // Constructor
~CWeightedSignal(void); // Destructor

bool AddSignal(string name, double weight); // Add a new signal source
bool UpdateWeight(string name, double weight); // Update an existing weight
virtual double LongSignal(void); // Calculate long signal
virtual double ShortSignal(void); // Calculate short signal
void Clear(void); // Clear all stored signals
};

//+------------------------------------------------------------------+
//| Constructor: Initializes the signal source array |
//+------------------------------------------------------------------+
CWeightedSignal::CWeightedSignal(void)
{
m_signal_sources = new CArrayObj();
}

//+------------------------------------------------------------------+
//| Destructor: Clears memory and deletes allocated objects |
//+------------------------------------------------------------------+
CWeightedSignal::~CWeightedSignal(void)
{
Clear();
delete m_signal_sources;
}

//+------------------------------------------------------------------+
//| Add a new signal source to the array |
//| Parameters: |
//| - name: The identifier for the signal source |
//| - weight: The importance assigned to the signal (must be >= 0) |
//| Returns: True if successfully added, otherwise false |
//+------------------------------------------------------------------+
bool CWeightedSignal::AddSignal(string name, double weight)
{
if(weight < 0.0)
return(false);

// Create a new signal source
SignalSource *source = new SignalSource();
source.name = name;
source.weight = weight;

// Add to the signal array
return m_signal_sources.Add(source) >= 0;
}

//+------------------------------------------------------------------+
//| Update the weight of an existing signal source |
//| Parameters: |
//| - name: The signal source identifier |
//| - weight: The new weight value (must be >= 0) |
//| Returns: True if update is successful, otherwise false |
//+------------------------------------------------------------------+
bool CWeightedSignal::UpdateWeight(string name, double weight)
{
if(weight < 0.0)
return(false);

for(int i = 0; i < m_signal_sources.Total(); i++)
{
SignalSource *source = (SignalSource *)m_signal_sources.At(i);
if(source.name == name)
{
source.weight = weight;
return(true);
}
}
return(false);
}

//+------------------------------------------------------------------+
//| Compute the long signal strength |
//| Returns: Weighted average of all long signals |
//+------------------------------------------------------------------+
double CWeightedSignal::LongSignal(void)
{
double total_weight = 0.0;
double weighted_signal = 0.0;

for(int i = 0; i < m_signal_sources.Total(); i++)
{
SignalSource *source = (SignalSource *)m_signal_sources.At(i);
double signal_value = SignalGetValue(source.name, ORDER_TYPE_BUY); // Fetch long signal value
weighted_signal += signal_value * source.weight;
total_weight += source.weight;
}

return (total_weight > 0.0) ? (weighted_signal / total_weight) : 0.0;
}

//+------------------------------------------------------------------+
//| Compute the short signal strength |
//| Returns: Weighted average of all short signals |
//+------------------------------------------------------------------+
double CWeightedSignal::ShortSignal(void)
{
double total_weight = 0.0;
double weighted_signal = 0.0;

for(int i = 0; i < m_signal_sources.Total(); i++)
{
SignalSource *source = (SignalSource *)m_signal_sources.At(i);
double signal_value = SignalGetValue(source.name, ORDER_TYPE_SELL); // Fetch short signal value
weighted_signal += signal_value * source.weight;
total_weight += source.weight;
}

return (total_weight > 0.0) ? (weighted_signal / total_weight) : 0.0;
}

//+------------------------------------------------------------------+
//| Clear all stored signal sources |
//+------------------------------------------------------------------+
void CWeightedSignal::Clear(void)
{
for(int i = 0; i < m_signal_sources.Total(); i++)
{
SignalSource *source = (SignalSource *)m_signal_sources.At(i);
delete source;
}
m_signal_sources.Clear();
}

Explanation

This MQL5 script defines the CWeightedSignal class, which calculates trading signals using multiple weighted sources. The key functionalities include:

  1. Adding and Managing Signal Sources:

    • AddSignal(): Registers a new signal source with a specified weight.
    • UpdateWeight(): Modifies the weight of an existing signal source.
    • Clear(): Removes all registered signals.
  2. Signal Calculation:

    • LongSignal(): Computes a weighted average of long signals.
    • ShortSignal(): Computes a weighted average of short signals.
  3. Memory Management:

    • The constructor initializes a dynamic array.
    • The destructor ensures all memory is freed properly.

This design allows flexible signal weighting, making it useful for multi-strategy trading systems.

ta psar

Resolving the “X does not have valid feature names” Warning in RandomForestClassifier

When using scikit-learn’s RandomForestClassifier, you might encounter the following warning during prediction:

UserWarning: X does not have valid feature names, but RandomForestClassifier was fitted with feature names

python
复制
编辑

This warning typically occurs under two main scenarios:

Causes

  1. Inconsistent Data Formats Between Training and Prediction:

    • Training Phase: If you trained your model using a pandas.DataFrame, the model records the feature names.
    • Prediction Phase: If you later pass a numpy.ndarray (which lacks column names) for prediction, the model warns that the feature names are missing.
  2. Mismatch in Feature Names:

    • Even if using DataFrames, if the order or names of the features in the prediction data do not exactly match those used during training, the warning may appear.

Solutions

1. Use Consistent Data Formats

Ensure that both your training and prediction data are in the same format. For example, if you use a pandas.DataFrame during training, use a DataFrame for prediction as well.

Example:

import pandas as pd
from sklearn.ensemble import RandomForestClassifier

# Training data as a DataFrame
X_train = pd.DataFrame({
    'feature1': [1, 2, 3],
    'feature2': [4, 5, 6]
})
y_train = [0, 1, 0]

# Train the model
model = RandomForestClassifier()
model.fit(X_train, y_train)

# Prediction data as a DataFrame with the same feature names
X_test = pd.DataFrame({
    'feature1': [7, 8],
    'feature2': [9, 10]
})

# Predict
predictions = model.predict(X_test)
print(predictions)
2. Ensure Feature Names and Order Match
If you must use a numpy.ndarray for prediction, make sure it has the same feature order and shape as the training data. Alternatively, convert the array into a DataFrame with the same column names as used during training.

Example:

python
复制
编辑
import numpy as np
import pandas as pd

# Suppose these are your trained feature names:
feature_names = ['feature1', 'feature2']

# Prediction data as a numpy array
X_test_array = np.array([[7, 9],
                         [8, 10]])

# Convert the array to DataFrame with the same feature names
X_test = pd.DataFrame(X_test_array, columns=feature_names)

# Now predict
predictions = model.predict(X_test)
print(predictions)
Summary
Warning Reason: The warning occurs because the model was fitted using DataFrames with valid feature names, but prediction was attempted with data lacking these names.
Fix: Ensure that the prediction data is in the same format (and with the same feature names) as the training data. Using pandas.DataFrame for both training and prediction is a straightforward way to resolve this issue.
Best Practice: Maintain consistency in your data formats throughout the model pipeline to avoid potential discrepancies and warnings.
By following these guidelines, you can prevent the warning and ensure that your model's predictions are based on correctly formatted data.

kalman

Kalman Filter in Forex Trading

1. What is the Kalman Filter?

The Kalman Filter (KF) is an optimal recursive estimation algorithm used to process noisy data and provide a smoothed estimate in uncertain conditions. It is widely used in navigation, signal processing, and financial time-series analysis.

Applications in Forex Trading:

Smooth price data, reducing market noise.
Predict future prices, based on historical data.
Alternative to moving averages, providing a more responsive trend-following indicator.


2. Mathematical Principles of the Kalman Filter

The Kalman Filter operates in two main steps:

Prediction Step

Predict the next system state:
[
\hat{x}k^- = A \hat{x}{k-1} + B u_k + w_k
]
Where:

  • (\hat{x}_k^-) = Predicted state.
  • (A) = State transition matrix (usually set to 1).
  • (B u_k) = Control input (often ignored).
  • (w_k) = Process noise.

Correction Step

Update the prediction using measurement (z_k):
[
K_k = P_k^- H^T (H P_k^- H^T + R)^{-1}
]
[
\hat{x}_k = \hat{x}_k^- + K_k (z_k - H \hat{x}_k^-)
]
[
P_k = (I - K_k H) P_k^-
]
Where:

  • (K_k) = Kalman gain (balances prediction and observation).
  • (H) = Observation matrix (usually set to 1).
  • (P_k) = Error covariance matrix.
  • (R) = Measurement noise.

3. Kalman Filter in Forex Trading

Key Uses:

Price Smoothing: Reduces short-term fluctuations and makes trends clearer.
Trend Following: Adapts to market changes faster than traditional moving averages.
Price Prediction: Can be integrated into AI-based trading systems.


4. MQL5 Implementation of the Kalman Filter

Below is an MQL5 implementation of the Kalman Filter, which smooths price data and plots it on the chart.

//+------------------------------------------------------------------+
//| Kalman Filter for Forex Trading                                 |
//+------------------------------------------------------------------+
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_color1 Blue

// Indicator buffer
double KalmanLine[];
input double ProcessNoise = 1e-3;  // Process noise
input double MeasurementNoise = 1e-2; // Measurement noise

// Initialization
int OnInit()
{
    SetIndexBuffer(0, KalmanLine);
    IndicatorShortName("Kalman Filter");
    return INIT_SUCCEEDED;
}

// Kalman Filter Calculation
void OnCalculate(const int rates_total,
                 const int prev_calculated,
                 const double &price[])
{
    if (rates_total < 10) return;

    // Initialize variables
    double x_est = price[0];   // Initial estimate
    double p_est = 1;          // Error covariance
    double K;                  // Kalman gain

    for (int i = 1; i < rates_total; i++)
    {
        // Prediction step
        double x_pred = x_est;
        double p_pred = p_est + ProcessNoise;

        // Compute Kalman gain
        K = p_pred / (p_pred + MeasurementNoise);

        // Update estimate
        x_est = x_pred + K * (price[i] - x_pred);
        p_est = (1 - K) * p_pred;

        // Store in buffer
        KalmanLine[i] = x_est;
    }
}

hybrid-transformer

Hybrid-Transformer 外汇高频交易 AI 实现

📌 1. 项目架构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Forex_HFT_AI/
├── data/ # 外汇数据存储
│ ├── tick_data.csv # 高频交易数据(毫秒级)
│ ├── order_book.csv # 订单簿数据
├── src/
│ ├── data_processing.py # 数据清洗与特征工程
│ ├── feature_engineering.py # 高频交易特征提取
│ ├── model_training.py # AI 交易模型训练
│ ├── backtesting.py # 回测系统
│ ├── execution.py # 交易执行(API对接)
│ ├── risk_management.py # 资金管理与风险控制
│ ├── main.py # 主程序
├── model/
│ ├── hft_model.pth # 训练好的AI模型
│ ├── scaler.pkl # 数据标准化工具
├── config.yaml # 交易参数配置
└── requirements.txt # 依赖环境

📌 2. Hybrid-Transformer 交易模型

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
import torch
import torch.nn as nn

class HybridTransformer(nn.Module):
def __init__(self, input_dim, hidden_dim=128, num_heads=4, num_layers=2):
super(HybridTransformer, self).__init__()

# CNN 层(局部模式识别)
self.conv1 = nn.Conv1d(in_channels=input_dim, out_channels=32, kernel_size=3, padding=1)
self.conv2 = nn.Conv1d(in_channels=32, out_channels=64, kernel_size=3, padding=1)
self.pool = nn.MaxPool1d(kernel_size=2)

# LSTM 层(短期趋势建模)
self.lstm = nn.LSTM(64, hidden_dim, batch_first=True)

# Transformer 层(长期趋势捕捉)
self.encoder_layer = nn.TransformerEncoderLayer(d_model=hidden_dim, nhead=num_heads, dim_feedforward=256)
self.transformer = nn.TransformerEncoder(self.encoder_layer, num_layers=num_layers)

# 全连接层(输出交易信号)
self.fc = nn.Linear(hidden_dim, 3) # 3个类别(买入 / 卖出 / 观望)

def forward(self, x):
# CNN 层提取局部特征
x = x.permute(0, 2, 1) # (Batch, Features, Time)
x = self.pool(nn.ReLU()(self.conv1(x)))
x = self.pool(nn.ReLU()(self.conv2(x)))
x = x.permute(0, 2, 1) # (Batch, Time, Features)

# LSTM 提取短期趋势
x, _ = self.lstm(x)

# Transformer 捕捉长期趋势
x = self.transformer(x)

# 取最后时间步的输出
x = x[:, -1, :]

return self.fc(x) # (Batch, 3)

📌 3. 交易策略

1
2
3
4
5
def trading_decision(model, X):
"""模型预测交易信号"""
prediction = model(torch.tensor(X, dtype=torch.float32)).detach().numpy()
action = np.argmax(prediction)
return "buy" if action == 1 else "sell" if action == -1 else "hold"

📌 4. 交易执行(MT5 API)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import MetaTrader5 as mt5

def place_order(symbol, order_type, volume=1.0):
"""执行交易"""
mt5.initialize()
order = {
"action": mt5.TRADE_ACTION_DEAL,
"symbol": symbol,
"volume": volume,
"type": mt5.ORDER_TYPE_BUY if order_type == "buy" else mt5.ORDER_TYPE_SELL,
"price": mt5.symbol_info_tick(symbol).ask if order_type == "buy" else mt5.symbol_info_tick(symbol).bid,
"deviation": 10,
"magic": 0,
"comment": "Hybrid Transformer AI",
"type_time": mt5.ORDER_TIME_GTC,
"type_filling": mt5.ORDER_FILLING_IOC,
}
return mt5.order_send(order)

📌 5. 交易回测

1
2
3
4
5
6
7
8
9
10
11
from backtesting import Backtest, Strategy

class HFTStrategy(Strategy):
def init(self):
pass

def next(self):
if self.data.imbalance[-1] > 0.5:
self.buy()
elif self.data.imbalance[-1] < -0.5:
self.sell()

🚀 结论

  1. Hybrid-Transformer = CNN + LSTM + Transformer 组合,提高交易预测精度。
  2. 适用于外汇高频交易(HFT)和趋势预测
  3. 结合 MT5 API 实盘交易,实现自动化交易策略

💡 下一步:优化 超参数、低延迟交易执行、强化学习 RL 交易策略!🔥

First Post

ha ha ha