lib/SINWAV.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 "SINWAV.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 SINWAV::SINWAV ()
00032 {
00033   pluginName = "SINWAV";
00034   helpFile = "sinwav.html";
00035 
00036   colorSinLabel = "colorSin";
00037   colorLeadLabel = "colorLead";
00038   labelSinLabel = "labelSin";
00039   labelLeadLabel = "labelLead";
00040   lineTypeSinLabel = "lineTypeSin";
00041   lineTypeLeadLabel = "lineTypeLead";
00042   pluginLabel = "plugin";
00043     
00044   setDefaults();
00045 }
00046 
00047 SINWAV::~SINWAV ()
00048 {
00049 }
00050 
00051 void SINWAV::setDefaults ()
00052 {
00053   colorSin.setNamedColor("red");
00054   colorLead.setNamedColor("blue");
00055   lineTypeSin = PlotLine::Line;
00056   lineTypeLead = PlotLine::Line;
00057   labelSin = pluginName;
00058   labelLead = "Lead";
00059 }
00060 
00061 Indicator * SINWAV::calculate ()
00062 {
00063   Indicator *output = new Indicator;
00064   output->setDateFlag(dateFlag);
00065   output->setLogScale(logScale);
00066 
00067   QPtrList<PlotLine> pll;
00068   pll.setAutoDelete(FALSE);
00069   getSINWAV(pll);
00070 
00071   int loop;
00072   for (loop = 0; loop < (int) pll.count(); loop++)
00073     output->addLine(pll.at(loop));
00074 
00075   return output;
00076 }
00077 
00078 void SINWAV::getSINWAV (QPtrList<PlotLine> &pll)
00079 {
00080   // Ehler's sine wave 
00081   
00082   PlotLine *Price = new PlotLine;
00083         
00084   int i = 0;
00085         
00086   // price = (h + l) / 2
00087   for (i = 0; i < (int) data->count(); i++)
00088     Price->append((data->getHigh(i) + data->getLow(i)) / 2);
00089                 
00090   //! VERSION 2
00091                 
00092   QMemArray<double> *smooth = new QMemArray<double>(Price->getSize());
00093   smooth->fill(0.0);
00094   QMemArray<double> *detrender = new QMemArray<double>(Price->getSize());
00095   detrender->fill(0.0);
00096   QMemArray<double> *period = new QMemArray<double>(Price->getSize());
00097   period->fill(0.0);
00098   QMemArray<double> *Q1 = new QMemArray<double>(Price->getSize());
00099   Q1->fill(0.0);
00100   QMemArray<double> *I1 = new QMemArray<double>(Price->getSize());
00101   I1->fill(0.0);
00102   QMemArray<double> *jI = new QMemArray<double>(Price->getSize());
00103   jI->fill(0.0);
00104   QMemArray<double> *jQ = new QMemArray<double>(Price->getSize());
00105   jQ->fill(0.0);
00106   QMemArray<double> *I2 = new QMemArray<double>(Price->getSize());
00107   I2->fill(0.0);
00108   QMemArray<double> *Q2 = new QMemArray<double>(Price->getSize());
00109   Q2->fill(0.0);
00110   QMemArray<double> *Re = new QMemArray<double>(Price->getSize());
00111   Re->fill(0.0);
00112   QMemArray<double> *Im = new QMemArray<double>(Price->getSize());
00113   Im->fill(0.0);
00114   QMemArray<double> *SmoothPrice = new QMemArray<double>(Price->getSize());
00115   SmoothPrice->fill(0.0);
00116   QMemArray<double> *DCPhase = new QMemArray<double>(Price->getSize());
00117   DCPhase->fill(0.0);
00118         
00119   PlotLine *out1 = new PlotLine;
00120   PlotLine *out2 = new PlotLine;
00121         
00122   double SmoothPeriod = 0;
00123   double DCPeriod = 0;
00124         
00125   for (i = 6; i< Price->getSize(); i++)
00126   {
00127     // Weighted price
00128     smooth->at(i) = ( 4 * Price->getData(i) + 3 * Price->getData(i-1) + 
00129                       2 * Price->getData(i-2) +  Price->getData(i-3)) /10.0;
00130                                                 
00131     detrender->at(i) = (0.0962 * smooth->at(i) + 0.5769 * smooth->at(i-2) - 
00132                         0.5769 * smooth->at(i-4) - 0.0962 * smooth->at(i-6)) *
00133                         (0.075 * period->at(i-1) + 0.54);
00134                 
00135     // Compute InPhase and Quadrature components
00136     Q1->at(i) = (0.0962 * detrender->at(i) + 0.5769 * detrender->at(i-2) - 
00137                  0.5769 * detrender->at(i-4) - 0.0962 * detrender->at(i-6)) *
00138                  (0.075 * period->at(i-1) + 0.54);
00139     I1->at(i) = detrender->at(i-3);
00140                 
00141     //Advance the phase of I1 and Q1 by 90 degrees
00142     jI->at(i) = (0.0962 * I1->at(i) + 0.5769 * I1->at(i-2) - 
00143                  0.5769 * I1->at(i-4) - 0.0962 * I1->at(i-6)) *
00144                  (0.075 * period->at(i-1) + 0.54);
00145                          
00146     Q1->at(i) = (0.0962 * Q1->at(i) + 0.5769 * Q1->at(i-2) - 
00147                  0.5769 * Q1->at(i-4) - 0.0962 * Q1->at(i-6)) *
00148                  (0.075 * period->at(i-1) + 0.54);
00149                                          
00150     // Phasor addition for 3-bar averaging      
00151     I2->at(i) = I1->at(i) - jQ->at(i);   
00152     Q2->at(i) = Q1->at(i) + jI->at(i);  
00153                 
00154     // Smooth the I and Q components before applying the discriminator
00155     I2->at(i) = 0.2 * I2->at(i) + 0.8 * I2->at(i-1);
00156     Q2->at(i) = 0.2 * Q2->at(i) + 0.8 * Q2->at(i-1);
00157                 
00158     // Homodyne Discriminator
00159     Re->at(i) = I2->at(i) * I2->at(i-1) + Q2->at(i) * Q2->at(i-1);
00160     Im->at(i) = I2->at(i) * Q2->at(i-1) - Q2->at(i) * I2->at(i-1);
00161     Re->at(i) = 0.2 * Re->at(i) + 0.8 * Re->at(i-1);
00162     Im->at(i) = 0.2 * Im->at(i) + 0.8 * Im->at(i-1);
00163     if (Im->at(i) != 0 && Re->at(i) != 0 )
00164       period->at(i) = 360/(atan(Im->at(i) / Re->at(i)) * (180/PI));
00165     if (period->at(i) > 1.5 * period->at(i-1))
00166       period->at(i) = 1.5 * period->at(i-1);
00167     if (period->at(i) < 0.67 * period->at(i-1))
00168       period->at(i) = 0.67 * period->at(i-1);
00169     if (period->at(i) < 6)
00170       period->at(i) = 6;
00171     if (period->at(i) > 50)
00172       period->at(i) = 50;
00173         
00174     period->at(i) = 0.2 * period->at(i) + 0.8 * period->at(i-1);
00175                 
00176     SmoothPeriod = 0.33 * period->at(i) + 0.67 * SmoothPeriod;
00177                 
00178     // Compute Dominant CyclePhase
00179     SmoothPrice->at(i) = (4 * Price->getData(i) + 3 * Price->getData(i-1) + 
00180                           2 * Price->getData(i-2) +  Price->getData(i-3)) /10.0;
00181                                                                   
00182     DCPeriod = (int)(SmoothPeriod + 0.5);
00183                 
00184     double RealPart = 0;
00185     double ImagPart = 0;
00186     int j = 0;
00187                 
00188     if (i >= (int)DCPeriod)
00189     {
00190       for (j = 0; j < (int)DCPeriod; j++)
00191       {
00192         RealPart = RealPart + sin((360 * (double)j / DCPeriod) * (PI/180)) * (SmoothPrice->at(i - j));
00193         ImagPart = ImagPart + cos((360 * (double)j / DCPeriod) * (PI/180)) * (SmoothPrice->at(i - j));
00194       }
00195     }
00196                 
00197     if (fabs(ImagPart) > 0.001)
00198       DCPhase->at(i) = atan(RealPart / ImagPart) * (180/PI);
00199                         
00200     if( fabs(ImagPart) <= 0.001 )
00201       DCPhase->at(i) = 90.0 * sin(RealPart * (PI/180));
00202                          
00203     DCPhase->at(i) = DCPhase->at(i) + 90.0;
00204                         
00205     // Compensate for one bar lag of the Weighted Moving Average
00206     DCPhase->at(i) = DCPhase->at(i) + 360.0 / SmoothPeriod;
00207                 
00208     if (ImagPart < 0) 
00209       DCPhase->at(i) = DCPhase->at(i) + 180.0;
00210                         
00211     if (DCPhase->at(i) > 315.0)
00212       DCPhase->at(i) = DCPhase->at(i) - 360.0;
00213                 
00214     // we're done....
00215     out1->append(sin(DCPhase->at(i) * (PI/180)));
00216     out2->append(sin((DCPhase->at(i) + 45.0) * (PI/180)));
00217   }
00218         
00219   delete smooth;
00220   delete detrender;
00221   delete period;
00222   delete Q1;
00223   delete I1;
00224   delete jI;
00225   delete jQ;
00226   delete I2;
00227   delete Q2;
00228   delete Re;
00229   delete Im;
00230   delete SmoothPrice;
00231   delete DCPhase;
00232   delete Price;
00233         
00234   out1->setColor(colorSin);
00235   out1->setLabel(labelSin);
00236   out1->setType(lineTypeSin);
00237   pll.append(out1);
00238         
00239   out2->setColor(colorLead);
00240   out2->setLabel(labelLead);
00241   out2->setType(lineTypeLead);
00242   pll.append(out2);
00243 }
00244 
00245 int SINWAV::indicatorPrefDialog (QWidget *w)
00246 {
00247   QString pl = QObject::tr("Parms");
00248   QString cl = QObject::tr("Sine Color");
00249   QString c2 = QObject::tr("Lead Color");
00250   QString ll = QObject::tr("Label");
00251   QString ltl = QObject::tr("Sine Line Type");
00252   QString lt2 = QObject::tr("Lead Line Type");
00253   
00254   PrefDialog *dialog = new PrefDialog(w);
00255   dialog->setCaption(QObject::tr("SINWAV Indicator"));
00256   dialog->createPage (pl);
00257   dialog->setHelpFile(helpFile);
00258   dialog->addColorItem(cl, pl, colorSin);
00259   dialog->addComboItem(ltl, pl, lineTypes, lineTypeSin);
00260   dialog->addColorItem(c2, pl, colorLead);
00261   dialog->addComboItem(lt2, pl, lineTypes, lineTypeLead);
00262   dialog->addTextItem(ll, pl, labelSin);
00263   
00264   int rc = dialog->exec();
00265   
00266   if (rc == QDialog::Accepted)
00267   {
00268     dialog->getColor(cl, colorSin);
00269     dialog->getColor(c2, colorLead);
00270     lineTypeSin = (PlotLine::LineType) dialog->getComboIndex(ltl);
00271     lineTypeLead = (PlotLine::LineType) dialog->getComboIndex(lt2);
00272     dialog->getText(ll, labelSin);
00273    
00274     rc = TRUE;
00275   }
00276   else
00277     rc = FALSE;
00278   
00279   delete dialog;
00280   return rc;
00281 }
00282 
00283 PlotLine * SINWAV::calculateCustom (QString &, QPtrList<PlotLine> &)
00284 {
00285   QPtrList<PlotLine> pll;
00286   pll.setAutoDelete(FALSE);
00287   getSINWAV(pll);
00288   pll.remove(1);
00289   return pll.at(0);
00290 }
00291 
00292 void SINWAV::getIndicatorSettings (Setting &dict)
00293 {
00294   QString ts = colorSin.name();
00295   dict.setData(colorSinLabel, ts);
00296   ts = colorLead.name();
00297   dict.setData(colorLeadLabel, ts);
00298   dict.setData(labelSinLabel, labelSin);
00299   dict.setData(labelLeadLabel, labelLead);
00300   ts = QString::number(lineTypeSin);
00301   dict.setData(lineTypeSinLabel, ts);
00302   ts = QString::number(lineTypeLead);
00303   dict.setData(lineTypeLeadLabel, ts);
00304   dict.setData(pluginLabel, pluginName);
00305 }
00306 
00307 void SINWAV::setIndicatorSettings (Setting &dict)
00308 {
00309   setDefaults();
00310   
00311   if (! dict.count())
00312     return;
00313   
00314   QString s;
00315   dict.getData(colorSinLabel, s);
00316   if (s.length())
00317     colorSin.setNamedColor(s);
00318         
00319   dict.getData(colorLeadLabel, s);
00320   if (s.length())
00321     colorLead.setNamedColor(s);
00322     
00323   dict.getData(labelSinLabel, s);
00324   if (s.length())
00325     labelSin = s;
00326         
00327   dict.getData(labelLeadLabel, s);
00328   if (s.length())
00329     labelLead = s;
00330         
00331   dict.getData(lineTypeSinLabel, s);
00332   if (s.length())
00333     lineTypeSin = (PlotLine::LineType) s.toInt();
00334         
00335   dict.getData(lineTypeLeadLabel, s);
00336   if (s.length())
00337     lineTypeLead = (PlotLine::LineType) s.toInt();
00338 }
00339 
00340 void SINWAV::formatDialog (QStringList &, QString &rv, QString &rs)
00341 {
00342   rs.truncate(0);
00343   rv.truncate(0);
00344   QString pl = QObject::tr("Parms");
00345   QString vnl = QObject::tr("Variable Name");
00346   PrefDialog *dialog = new PrefDialog(0);
00347   dialog->setCaption(QObject::tr("SINWAV Format"));
00348   dialog->createPage (pl);
00349   dialog->setHelpFile(helpFile);
00350 
00351   QString s;
00352   dialog->addTextItem(vnl, pl, s);
00353 
00354   int rc = dialog->exec();
00355 
00356   if (rc == QDialog::Accepted)
00357     dialog->getText(vnl, rv);
00358 
00359   delete dialog;
00360 }
00361