这几个月在做一个关于证券的项目,项目里一些图表的绘制,包括K线图以及相关指标算法的绘制让我有点为难,毕竟我也不炒股,没接触过过这些东西。原先是使用的ta-lib这个金融库来进行相关的计算。不过有些算法得出的结果有些不太理想(主要是和同花顺的数据进行对比),因此自己动手写了几个算法进行使用。趁现在有时间,记录下计算过程。在计算前首先要明白MA的使用,MA表示移动平均,
即MA(X,10)= (x1+x2+x3+....+x10)/10;表示最近10天的X的平均数,X为数组,例如X可以取历史收盘价数据。
代码如下:
private void MA(float[] arr,int optInTimePeriod) {
double ma;
double closeSum = 0;
int period;
for (int i = 0; i < arr.length; i++) {
closeSum += arr[i];
if (i >= (optInTimePeriod - 1)) {
period = i - optInTimePeriod;
if (period >= 0) {
closeSum -= arr[period];
}
ma = (float) closeSum / optInTimePeriod;
}
}
}
封装的数据类:
public class ChartDataBean extends BaseBean {
public double[] open; //开盘价
public long[] time; //时间
public double[] volume; //成交量
public double[] high; //最高价
public double[] low; //最低价
public double[] close; //收盘价
public double[] avgPrice; //均价
public double[] price; //价格
public boolean isLastPage; //是否为最后一页数据
public AskBean askBean;
public BidBean bidBean;
public int length = 0;
public int newLength = 0;
public double preClose = 1;
}
1.MACD
MACD的图表中包含了dif,dea以及macd三个数据,要计算macd,首先要计算ema,ema表示的是n日的移动平均。
例如:12日EMA的计算:EMA(12) = MA(close,12)
以下以12为快速移动平均值,26为慢速平均值,则 差离值(DIF)的计算:
DIF = EMA(12) - EMA(26) 。
根据差离值计算其9日的EMA,即离差平均值,是所求的DEA值。
DEA = (前一日DEA X 8/10 + 今日DIF X 2/10)
MACD = (DIF-DEA)*2。
代码如下:
public void setMACD( int shortValue, int longValue, int mValue,) {
double emaShort = 0.0;
double emaLong = 0.0;
double macd;
double dif;
double dea = 0.0;
for (int i = 0; i < mChartData.close.length; i++) {
if (i == 0) {
emaShort =mChartData.close[i];
emaLong = mChartData.close[i];
dif = 0;
dea = 0;
macd = 0;
} else {
emaShort = (emaShort * (shortValue - 1) + mChartData.close[i] * 2) / (shortValue + 1);
emaLong = (emaLong * (longValue - 1) + mChartData.close[i] * 2) / (longValue + 1);
dif = emaShort - emaLong;
dea = (dea * (mValue - 1) + dif * 2) / (mValue + 1);
macd = (dif - dea) * 2;
}
}
}
2.EXPMA
EXPMA=[2*X+(N-1)*Y’]/(N+1),其中X表示的是当日收盘价,N为周期天数
代码如下:
public void EXPMA( int optInTimePeriod) {
double expma;
double preExpma = mChartData.close[0];
double a = 1.0 * 2 / (optInTimePeriod + 1);
for (int i = 0; i < mChartData.close.length; i++) {
if (i == 0) {
expma = mChartData.close[0];
} else {
expma = mChartData.close[i] * a + (1 - a) * preExpma;
}
preExpma = expma;
}
}
DMA涉及到两个数据,DMA,AMA,以下以10为短期平均值,50为长期平均值
DMA=MA(close,10)— MA(close,50)
AMA=MA(DMA,10)
代码如下:
public void setDMA(int shortValue, int longValue, int mValue,List firstData, List secondData) {
firstData.clear();
secondData.clear();
if (mChartData==null){
return;
}
double[] dma = new double[mChartData.close.length];
int period;
double dmaSum = 0;
double closeLongSum = 0;
double closeShortSum = 0;
double closeLongAve;
double closeShortAve;
for (int i = 0; i < mChartData.close.length; i++) {
closeLongSum += mChartData.close[i];
if (i >= (longValue - shortValue)) {
period = i - shortValue;
closeShortSum += mChartData.close[i];
if (period >= (longValue - shortValue)) {
closeShortSum -= mChartData.close[period];
}
}
if (i >= (longValue - 1)) {
period = i - longValue;
if (period >= 0) {
closeLongSum -= mChartData.close[period];
}
closeLongAve = closeLongSum / longValue;
closeShortAve = closeShortSum / shortValue;
dma[i] = closeShortAve - closeLongAve;
dmaSum += dma[i];
Entry dmaEntry = new Entry(i, (float) dma[i]);
firstData.add(dmaEntry);
if (i >= (longValue + mValue - 2)) {
period = i - mValue;
if (period >= (longValue - 1)) {
dmaSum -= dma[period];
}
Entry amaEntry = new Entry(i, (float) (dmaSum / mValue));
secondData.add(amaEntry);
}
}
}
}
public void setDMI(int m1, int m2,List firstData, List secondData, List thirdData, List fourthData) {
firstData.clear();
secondData.clear();
thirdData.clear();
fourthData.clear();
if (mChartData==null){
return;
}
double[] plusDi = new double[mChartData.close.length];
double[] minusDi = new double[mChartData.close.length];
double[] adx = new double[mChartData.close.length];
double[] tr = new double[mChartData.close.length];
double[] plusDm = new double[mChartData.close.length];
double[] minusDm = new double[mChartData.close.length];
double[] adxValue = new double[mChartData.close.length];
int period;
double adxValueSum = 0;
plusDi[0] = 0;
tr[0] = mChartData.high[0] - mChartData.low[0];
plusDm[0] = 0;
minusDm[0] = 0;
double sumPlusDm = 0;
double sumMinusDm = 0;
double sumTr = mChartData.high[0] - mChartData.low[0];
firstData.add(new Entry(0, (float) plusDi[0]));
secondData.add(new Entry(0, (float) minusDi[0]));
for (int i = 1; i < mChartData.close.length; i++) {
plusDm[i] = mChartData.high[i] - mChartData.high[i - 1];
minusDm[i] = mChartData.low[i - 1] - mChartData.low[i];
if (plusDm[i] < 0 || plusDm[i] <= minusDm[i]) {
plusDm[i] = 0;
}
if (minusDm[i] < 0 || minusDm[i] <= plusDm[i]) {
minusDm[i] = 0;
}
tr[i] = getAbsMax(mChartData.high[i] - mChartData.low[i], mChartData.high[i] - mChartData.close[i - 1], mChartData.low[i] - mChartData.close[i - 1]);
sumTr += tr[i];
sumPlusDm += plusDm[i];
sumMinusDm += minusDm[i];
if (i >= (m1 - 1)) {
period = i - m1;
if (period >= 0) {
sumPlusDm -= plusDm[period];
sumMinusDm -= minusDm[period];
sumTr -= tr[period];
}
}
plusDi[i] = 100.0 * sumPlusDm / sumTr;
minusDi[i] = 100 * sumMinusDm / sumTr;
Entry pdiEntry = new Entry(i, (float) plusDi[i]);
Entry mdiEntry = new Entry(i, (float) minusDi[i]);
firstData.add(pdiEntry);
secondData.add(mdiEntry);
adxValue[i] = Math.abs(minusDi[i] - plusDi[i]) / (minusDi[i] + plusDi[i]) * 100.0;
adxValueSum += adxValue[i];
if (i >= m2) {
adxValueSum -= adxValue[i - m2];
adx[i] = adxValueSum / m2;
Entry adxEntry = new Entry(i, (float) adx[i]);
thirdData.add(adxEntry);
}
if (i >= 2 * m2) {
Entry adxrEntry = new Entry(i, (float) ((adx[i] + adx[i - m2]) / 2));
fourthData.add(adxrEntry);
}
}
}
private double getAbsMax(double a, double b, double c) {
a = Math.abs(a);
b = Math.abs(b);
c = Math.abs(c);
double temp = Math.max(a, b);
return Math.max(temp, c);
}
public void setOBV() {
double obv;
double preObv = 0;
for (int i = 0; i < mChartData.close.length; i++) {
if (i == 0) {
obv = 0;
} else {
if (mChartData.close[i] > mChartData.close[i - 1]) {
obv = (preObv + mChartData.volume[i]);
} else if (mChartData.close[i] < mChartData.close[i - 1]) {
obv = (preObv - mChartData.volume[i]);
} else {
obv = preObv;
}
}
preObv = obv;
}
}