00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "VIDYA.h"
00023 #include "PrefDialog.h"
00024 #include <qdict.h>
00025 #include <qobject.h>
00026 #include <math.h>
00027 #include <qmemarray.h>
00028
00029 #define PI 3.14159265
00030
00031 VIDYA::VIDYA ()
00032 {
00033 pluginName = "VIDYA";
00034 helpFile = "vidya.html";
00035
00036 colorLabel = "color";
00037 labelLabel = "label";
00038 lineTypeLabel = "lineType";
00039 pluginLabel = "plugin";
00040 periodLabel = "period";
00041 volPeriodLabel = "volPeriod";
00042 inputLabel = "input";
00043
00044 formatList.append(FormatInputArray);
00045 formatList.append(FormatInteger);
00046 formatList.append(FormatInteger);
00047
00048 setDefaults();
00049 }
00050
00051 VIDYA::~VIDYA ()
00052 {
00053 }
00054
00055 void VIDYA::setDefaults ()
00056 {
00057 color.setNamedColor("cyan");
00058 lineType = PlotLine::Line;
00059 label = pluginName;
00060 period = 14;
00061 volPeriod = 10;
00062 input = BarData::Close;
00063 }
00064
00065 Indicator * VIDYA::calculate ()
00066 {
00067 Indicator *output = new Indicator;
00068 output->setDateFlag(dateFlag);
00069 output->setLogScale(logScale);
00070
00071 PlotLine *in = data->getInput(input);
00072 if (! in)
00073 {
00074 qDebug("VIDYA::calculate: no input");
00075 return output;
00076 }
00077
00078 if ( in->getSize() < period )
00079 {
00080 qDebug("VIDYA::calculate: insufficient data");
00081 return output;
00082 }
00083
00084 PlotLine *out = new PlotLine;
00085
00086 calcVidya (out, in, volPeriod, period);
00087
00088 out->setColor(color);
00089 out->setType(lineType);
00090 out->setLabel(pluginName);
00091 output->addLine(out);
00092 return output;
00093 }
00094
00095 void VIDYA::calcVidya (PlotLine *outSignal, PlotLine *inSignal, int iCmoPeriod, int iVidyaPeriod)
00096 {
00097 PlotLine *cmo = new PlotLine;
00098
00099 calcCMO(cmo, inSignal, iCmoPeriod);
00100
00101 int i = 0;
00102 int loop = (int)inSignal->getSize();
00103
00104 QMemArray<double> *inSeries = new QMemArray<double>(loop);
00105 inSeries->fill(0.0);
00106 QMemArray<double> *offset = new QMemArray<double>(loop);
00107 offset->fill(0.0);
00108 QMemArray<double> *absCmo = new QMemArray<double>(loop);
00109 absCmo->fill(0.0);
00110 QMemArray<double> *vidya = new QMemArray<double>(loop);
00111 vidya->fill(0.0);
00112
00113 double c = 2 / (double)iVidyaPeriod +1;
00114
00115 for ( i = 0; i < loop; i++)
00116 inSeries->at(i) = inSignal->getData(i);
00117
00118 int index = inSeries->size() -1;
00119 for (i = cmo->getSize() -1; i >= 0; i--)
00120 {
00121 absCmo->at(index) = fabs(cmo->getData(i) / 100);
00122 index--;
00123 }
00124
00125 for (i = iCmoPeriod + iVidyaPeriod; i < (int)inSeries->size(); i++)
00126 {
00127 vidya->at(i) = ( inSeries->at(i) * c * absCmo->at(i) ) + ( (1 - absCmo->at(i) * c) * vidya->at(i-1) );
00128
00129 outSignal->append(vidya->at(i));
00130 }
00131
00132 delete inSeries;
00133 delete offset;
00134 delete absCmo;
00135 delete vidya;
00136 delete cmo;
00137 }
00138
00139 void VIDYA::calcCMO ( PlotLine *outSignal, PlotLine *inSignal, int iPeriod)
00140 {
00141
00142
00143
00144 int loop = (int)inSignal->getSize();
00145
00146 QMemArray<double> *inSeries = new QMemArray<double>(loop);
00147 inSeries->fill(0.0);
00148 QMemArray<double> *offset = new QMemArray<double>(loop);
00149 offset->fill(0.0);
00150 QMemArray<double> *mom = new QMemArray<double>(loop);
00151 mom->fill(0.0);
00152 QMemArray<double> *posSeries = new QMemArray<double>(loop);
00153 posSeries->fill(0.0);
00154 QMemArray<double> *negSeries = new QMemArray<double>(loop);
00155 negSeries->fill(0.0);
00156 QMemArray<double> *sumPos = new QMemArray<double>(loop);
00157 sumPos->fill(0.0);
00158 QMemArray<double> *sumNeg = new QMemArray<double>(loop);
00159 sumNeg->fill(0.0);
00160 QMemArray<double> *cmoUp = new QMemArray<double>(loop);
00161 cmoUp->fill(0.0);
00162 QMemArray<double> *cmoDown = new QMemArray<double>(loop);
00163 cmoDown->fill(0.0);
00164 QMemArray<double> *rawCmo = new QMemArray<double>(loop);
00165 rawCmo->fill(0.0);
00166
00167 int i = 0;
00168
00169 for (i = 0; i < loop; i++)
00170 inSeries->at(i) = inSignal->getData(i);
00171
00172 for (i = iPeriod - 1; i < loop; i++)
00173 {
00174 offset->at(i) = inSeries->at(i-1);
00175
00176 mom->at(i) = inSeries->at(i) - offset->at(i);
00177
00178 if (mom->at(i) > 0)
00179 posSeries->at(i) = mom->at(i);
00180 else
00181 posSeries->at(i) = 0;
00182
00183 if (mom->at(i) < 0)
00184 negSeries->at(i) = fabs(mom->at(i));
00185 else
00186 negSeries->at(i) = 0;
00187
00188 int j = 0;
00189 double sumUp = 0;
00190 double sumDown = 0;
00191
00192 for (j = 0; j < iPeriod; j++)
00193 {
00194 sumUp += posSeries->at(i-j);
00195 sumDown += negSeries->at(i-j);
00196 }
00197
00198 sumPos->at(i) = sumUp;
00199 sumNeg->at(i) = sumDown;
00200
00201 cmoUp->at(i) = 100 * ((sumPos->at(i) - sumNeg->at(i)));
00202
00203 cmoDown->at(i) = sumPos->at(i) + sumNeg->at(i);
00204
00205 rawCmo->at(i) = cmoUp->at(i) / cmoDown->at(i);
00206
00207 if (i > iPeriod -1)
00208 outSignal->append(rawCmo->at(i));
00209 }
00210
00211 delete inSeries;
00212 delete offset;
00213 delete mom;
00214 delete posSeries;
00215 delete negSeries;
00216 delete sumPos;
00217 delete sumNeg;
00218 delete cmoUp;
00219 delete cmoDown;
00220 delete rawCmo;
00221 }
00222
00223 void VIDYA::calcAdaptCMO ( PlotLine *outSignal, PlotLine *inSignal, int iStdPeriod,
00224 int iMinLook, int iMaxLook)
00225 {
00226
00227
00228
00229
00230 PlotLine *currentLookback = new PlotLine;
00231
00232 getStdDev(currentLookback, inSignal, iStdPeriod);
00233
00234 getNorm( currentLookback, iMinLook, iMaxLook );
00235
00236 int i = 0;
00237
00238 for (i = 0; i < currentLookback->getSize(); i++)
00239 currentLookback->setData( i, (int)currentLookback->getData(i) );
00240
00241 int loop = (int)inSignal->getSize();
00242
00243 QMemArray<double> *inSeries = new QMemArray<double>(loop);
00244 inSeries->fill(0.0);
00245 QMemArray<double> *offset = new QMemArray<double>(loop);
00246 offset->fill(0.0);
00247 QMemArray<double> *mom = new QMemArray<double>(loop);
00248 mom->fill(0.0);
00249 QMemArray<double> *posSeries = new QMemArray<double>(loop);
00250 posSeries->fill(0.0);
00251 QMemArray<double> *negSeries = new QMemArray<double>(loop);
00252 negSeries->fill(0.0);
00253 QMemArray<double> *sumPos = new QMemArray<double>(loop);
00254 sumPos->fill(0.0);
00255 QMemArray<double> *sumNeg = new QMemArray<double>(loop);
00256 sumNeg->fill(0.0);
00257 QMemArray<double> *cmoUp = new QMemArray<double>(loop);
00258 cmoUp->fill(0.0);
00259 QMemArray<double> *cmoDown = new QMemArray<double>(loop);
00260 cmoDown->fill(0.0);
00261 QMemArray<double> *currentLook = new QMemArray<double>(loop);
00262 currentLook->fill(0.0);
00263 QMemArray<double> *adaptCmo = new QMemArray<double>(loop);
00264 adaptCmo->fill(0.0);
00265
00266
00267 int index = currentLook->size() -1;
00268 for (i = currentLookback->getSize() -1; i >=0; i--)
00269 {
00270 currentLook->at(index) = currentLookback->getData(i);
00271 index--;
00272 }
00273
00274 for (i = 0; i < loop; i++)
00275 inSeries->at(i) = inSignal->getData(i);
00276
00277 for (i = iStdPeriod - 1; i < loop; i++)
00278 {
00279 offset->at(i) = inSeries->at(i-1);
00280
00281 mom->at(i) = inSeries->at(i) - offset->at(i);
00282
00283 if (mom->at(i) > 0)
00284 posSeries->at(i) = mom->at(i);
00285 else
00286 posSeries->at(i) = 0;
00287
00288 if (mom->at(i) < 0)
00289 negSeries->at(i) = fabs(mom->at(i));
00290 else
00291 negSeries->at(i) = 0;
00292
00293 int j = 0;
00294 double sumUp = 0;
00295 double sumDown = 0;
00296
00297 for (j = 0; j < (int)currentLook->at(i); j++)
00298 {
00299 sumUp += posSeries->at(i-j);
00300 sumDown += negSeries->at(i-j);
00301 }
00302
00303 sumPos->at(i) = sumUp;
00304 sumNeg->at(i) = sumDown;
00305
00306 cmoUp->at(i) = 100 * ((sumPos->at(i) - sumNeg->at(i)));
00307
00308 cmoDown->at(i) = sumPos->at(i) + sumNeg->at(i);
00309
00310 adaptCmo->at(i) = cmoUp->at(i) / cmoDown->at(i);
00311
00312 if (i > iStdPeriod -1)
00313 outSignal->append(adaptCmo->at(i));
00314 }
00315
00316 delete inSeries;
00317 delete offset;
00318 delete mom;
00319 delete posSeries;
00320 delete negSeries;
00321 delete sumPos;
00322 delete sumNeg;
00323 delete cmoUp;
00324 delete cmoDown;
00325 delete adaptCmo;
00326 delete currentLook;
00327 delete currentLookback;
00328 }
00329
00330 void VIDYA::getStdDev( PlotLine *outLine, PlotLine *inLine, int iPeriod )
00331 {
00332 int loop;
00333
00334 for (loop = iPeriod -1; loop < (int) inLine->getSize(); loop++)
00335 {
00336 double mean = 0;
00337 int loop2;
00338 for (loop2 = 0; loop2 < iPeriod; loop2++)
00339 mean += inLine->getData(loop - loop2);
00340
00341 mean /= (double)iPeriod;
00342
00343 double ds = 0;
00344 for (loop2 = 0; loop2 < iPeriod; loop2++)
00345 {
00346 double t = inLine->getData(loop - loop2) - mean;
00347 ds += (t * t);
00348 }
00349
00350 ds = sqrt(ds / (double)period);
00351 outLine->append(ds);
00352 }
00353 }
00354
00355 void VIDYA::getNorm( PlotLine *inSig, double iMin, double iMax)
00356 {
00357
00358
00359 int i = 0;
00360 double range = 0;
00361 double max = -999999;
00362 double min = 999999;
00363 double norm = 0;
00364 for (i = 0; i < inSig->getSize(); i++)
00365 {
00366 if(inSig->getData(i) > max)
00367 max = inSig->getData(i);
00368
00369 if(inSig->getData(i) < min)
00370 min = inSig->getData(i);
00371 }
00372
00373 range = fabs(max) + fabs(min);
00374
00375 for (i = 0; i < inSig->getSize(); i++)
00376 {
00377 norm = iMin + (iMax - iMin) * ( (inSig->getData(i) - min) / (max - min) );
00378 inSig->setData(i, norm);
00379 }
00380 }
00381
00382 int VIDYA::indicatorPrefDialog (QWidget *w)
00383 {
00384 QString pl = QObject::tr("Parms");
00385 QString cl = QObject::tr("Color");
00386 QString ll = QObject::tr("Label");
00387 QString ltl = QObject::tr("Line Type");
00388 QString perl = QObject::tr("Vidya period");
00389 QString per2 = QObject::tr("Volatility Period");
00390 QString il = QObject::tr("Input");
00391
00392 PrefDialog *dialog = new PrefDialog(w);
00393 dialog->setCaption(QObject::tr("VIDYA Indicator"));
00394 dialog->createPage (pl);
00395 dialog->setHelpFile(helpFile);
00396 dialog->addIntItem(perl, pl, period, 2, 50);
00397 dialog->addIntItem(per2, pl, volPeriod, 2, 50);
00398 dialog->addColorItem(cl, pl, color);
00399 dialog->addTextItem(ll, pl, label);
00400 dialog->addComboItem(ltl, pl, lineTypes, lineType);
00401 dialog->addComboItem(il, pl, inputTypeList, input);
00402
00403 pl = QObject::tr("Zones");
00404 dialog->createPage (pl);
00405
00406 int rc = dialog->exec();
00407
00408 if (rc == QDialog::Accepted)
00409 {
00410 dialog->getColor(cl, color);
00411 lineType = (PlotLine::LineType) dialog->getComboIndex(ltl);
00412 dialog->getText(ll, label);
00413 period = dialog->getInt(perl);
00414 volPeriod = dialog->getInt(per2);
00415 input = (BarData::InputType) dialog->getComboIndex(il);
00416
00417 rc = TRUE;
00418 }
00419 else
00420 rc = FALSE;
00421
00422 delete dialog;
00423
00424 return rc;
00425 }
00426
00427 PlotLine * VIDYA::calculateCustom (QString &p, QPtrList<PlotLine> &d)
00428 {
00429
00430
00431 if (checkFormat(p, d, 3, 3))
00432 return 0;
00433
00434 period = formatStringList[1].toInt();
00435 volPeriod = formatStringList[2].toInt();
00436
00437 PlotLine *out = new PlotLine;
00438 calcVidya (out, d.at(0), volPeriod, period);
00439 return out;
00440 }
00441
00442 void VIDYA::getIndicatorSettings (Setting &dict)
00443 {
00444 QString ts = color.name();
00445 dict.setData(colorLabel, ts);
00446 dict.setData(labelLabel, label);
00447 ts = QString::number(lineType);
00448 dict.setData(lineTypeLabel, ts);
00449 dict.setData(pluginLabel, pluginName);
00450 ts = QString::number(period);
00451 dict.setData(periodLabel, ts);
00452 ts = QString::number(volPeriod);
00453 dict.setData(volPeriodLabel, ts);
00454 ts = QString::number(input);
00455 dict.setData(inputLabel, ts);
00456 }
00457
00458 void VIDYA::setIndicatorSettings (Setting &dict)
00459 {
00460 setDefaults();
00461
00462 if (! dict.count())
00463 return;
00464
00465 QString s;
00466 dict.getData(colorLabel, s);
00467 if (s.length())
00468 color.setNamedColor(s);
00469
00470 dict.getData(labelLabel, s);
00471 if (s.length())
00472 label = s;
00473
00474 dict.getData(lineTypeLabel, s);
00475 if (s.length())
00476 lineType = (PlotLine::LineType) s.toInt();
00477
00478 dict.getData(periodLabel, s);
00479 if (s.length())
00480 period = s.toInt();
00481
00482 dict.getData(volPeriodLabel, s);
00483 if (s.length())
00484 volPeriod = s.toInt();
00485
00486 dict.getData(inputLabel, s);
00487 if (s.length())
00488 input = (BarData::InputType) s.toInt();
00489 }
00490
00491 void VIDYA::formatDialog (QStringList &vl, QString &rv, QString &rs)
00492 {
00493 rs.truncate(0);
00494 rv.truncate(0);
00495 QString pl = QObject::tr("Parms");
00496 QString vnl = QObject::tr("Variable Name");
00497 QString perl = QObject::tr("Vidya period");
00498 QString per2 = QObject::tr("Volatility Period");
00499 QString il = QObject::tr("Input");
00500 PrefDialog *dialog = new PrefDialog(0);
00501 dialog->setCaption(QObject::tr("VIDYA Format"));
00502 dialog->createPage (pl);
00503 dialog->setHelpFile(helpFile);
00504
00505
00506
00507 QString s;
00508 dialog->addTextItem(vnl, pl, s);
00509 dialog->addComboItem(il, pl, vl, input);
00510 dialog->addIntItem(perl, pl, period, 2, 50);
00511 dialog->addIntItem(per2, pl, volPeriod, 2, 50);
00512
00513 int rc = dialog->exec();
00514
00515 if (rc == QDialog::Accepted)
00516 {
00517 dialog->getText(vnl, rv);
00518
00519 dialog->getCombo(il, rs);
00520
00521 int t = dialog->getInt(perl);
00522 rs.append("," + QString::number(t));
00523
00524 t = dialog->getInt(per2);
00525 rs.append("," + QString::number(t));
00526 }
00527
00528 delete dialog;
00529 }
00530