用.NET语言写一个计算股票技术指标DMI的函数,第一个参数为datatable类型,另外两个参数为int型;日期列名为“日期”,开盘价列名为“开盘”,收盘价列名为“收盘”,最高价列名为“最高”,最低价列名为“最低”,返回值为datatable类型,返回值包含PDI,MDI,ADX,ADXR等列。
时间: 2024-03-27 10:41:29 浏览: 150
好的,以下是计算DMI指标的函数代码:
```csharp
public static DataTable CalculateDMI(DataTable dt, int n, int m)
{
// 计算方向线DI和动态区间范围TR
double[] DIp = new double[dt.Rows.Count];
double[] DIn = new double[dt.Rows.Count];
double[] TR = new double[dt.Rows.Count];
for (int i = 1; i < dt.Rows.Count; i++)
{
double high = Convert.ToDouble(dt.Rows[i]["最高"]);
double low = Convert.ToDouble(dt.Rows[i]["最低"]);
double pre_close = Convert.ToDouble(dt.Rows[i - 1]["收盘"]);
double pdm = Math.Max(high - pre_close, 0);
double ndm = Math.Max(pre_close - low, 0);
DIp[i] = pdm;
DIn[i] = ndm;
TR[i] = Math.Max(Math.Max(high - low, Math.Abs(high - pre_close)), Math.Abs(low - pre_close));
}
// 计算平均动向指标ADX和动向指标DI
double[] DX = new double[dt.Rows.Count];
double[] ADX = new double[dt.Rows.Count];
double[] ADXR = new double[dt.Rows.Count];
for (int i = n + m - 2; i < dt.Rows.Count; i++)
{
double sum_dip = 0, sum_din = 0, sum_tr = 0;
for (int j = i - n + 1; j <= i; j++)
{
sum_dip += DIp[j];
sum_din += DIn[j];
sum_tr += TR[j];
}
double pdi = 100 * sum_dip / sum_tr;
double ndi = 100 * sum_din / sum_tr;
double dx = 100 * Math.Abs(pdi - ndi) / (pdi + ndi);
DX[i] = dx;
if (i == n + m - 2)
{
double sum_dx = 0;
for (int j = i - n + 1; j <= i; j++)
{
sum_dx += DX[j];
}
ADX[i] = sum_dx / n;
}
else if (i > n + m - 2)
{
ADX[i] = (ADX[i - 1] * (n - 1) + DX[i]) / n;
}
if (i >= n + m - 2 + m - 1)
{
ADXR[i] = (ADX[i] + ADX[i - m + 1]) / 2;
}
}
// 构造返回结果
DataTable result = new DataTable();
result.Columns.Add("日期", typeof(DateTime));
result.Columns.Add("PDI", typeof(double));
result.Columns.Add("MDI", typeof(double));
result.Columns.Add("ADX", typeof(double));
result.Columns.Add("ADXR", typeof(double));
for (int i = n + m - 2 + m - 1; i < dt.Rows.Count; i++)
{
DataRow row = result.NewRow();
row["日期"] = dt.Rows[i]["日期"];
row["PDI"] = Math.Round(100 * DIp[i] / TR[i], 3);
row["MDI"] = Math.Round(100 * DIn[i] / TR[i], 3);
row["ADX"] = Math.Round(ADX[i], 3);
row["ADXR"] = Math.Round(ADXR[i], 3);
result.Rows.Add(row);
}
return result;
}
```
这个函数与上一个函数的区别在于,多了两个参数n和m,用于指定计算DI和ADX时的时间窗口大小。如果n和m都为14,则相当于上一个函数中的默认设置。同时,这个函数也假定输入的数据表dt已经按照日期升序排列,而且至少包含n + m - 1 + m - 1 = 2m + n - 2行数据(因为要计算ADX和ADXR需要至少2m + n - 2个数据点)。如果数据不足,函数会返回空的结果表。
阅读全文