lib/VIDYA.cpp

Go to the documentation of this file.
00001 /*
00002  *  Qtstalker stock charter
00003  *
00004  *  Copyright (C) 2001-2007 Stefan S. Stratigakos
00005  *
00006  *  This program is free software; you can redistribute it and/or modify
00007  *  it under the terms of the GNU General Public License as published by
00008  *  the Free Software Foundation; either version 2 of the License, or
00009  *  (at your option) any later version.
00010  *
00011  *  This program is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *  GNU General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU General Public License
00017  *  along with this program; if not, write to the Free Software
00018  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
00019  *  USA.
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++)           // period safty
00126   {
00127     vidya->at(i) = ( inSeries->at(i) * c * absCmo->at(i) ) + ( (1 - absCmo->at(i) * c) * vidya->at(i-1) );
00128     //!  (Price*Const*AbsCMO) + ((1-AbsCMO*Const)*VIDYA[1]),Price);
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   //!  Chande Momentum Oscillator
00142   //!  Raw VIDYA 
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   //! Chande Momentum Oscillator
00227   //! Adaptaave VIDYA 
00228   //! Not used here, but it has possibilities....
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   // line up data
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   //    I = Imin + (Imax-Imin)*(V-Vmin)/(Vmax-Vmin)
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   // format1: ARRAY_INPUT, PERIOD, VOL_PERIOD
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   // format1: ARRAY_INPUT, PERIOD, VOL_PERIOD
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