lib/SZ.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 /* The "SafeZone Stop" indicator is described in
00023    Dr. Alexander Elder's book _Come Into My Trading Room_, p.173 */
00024 
00025 #include "SZ.h"
00026 #include <math.h>
00027 #include <stdio.h>
00028 #include "PrefDialog.h"
00029 #include <qdict.h>
00030 #include <qobject.h>
00031 
00032 SZ::SZ ()
00033 {
00034   pluginName = "SZ";
00035 
00036   colorLabel = "color";
00037   lineTypeLabel = "lineType";
00038   periodLabel = "period";
00039   noDeclinePeriodLabel = "noDeclinePeriod";
00040   coefficientLabel = "coefficient";
00041   methodLabel = "method";
00042   labelLabel = "label";
00043   pluginLabel = "plugin";
00044 
00045   // format1: METHOD, PERIOD, NO_DECLINE_PERIOD, COEFFICIENT
00046   formatList.append(FormatString);
00047   formatList.append(FormatInteger);
00048   formatList.append(FormatInteger);
00049   formatList.append(FormatDouble);
00050 
00051   setDefaults();
00052   methodList.append("Long");
00053   methodList.append("Short");
00054   helpFile = "sz.html";
00055 }
00056 
00057 SZ::~SZ ()
00058 {
00059 }
00060 
00061 void SZ::setDefaults ()
00062 {
00063   color.setNamedColor("white");
00064   lineType = PlotLine::Line;
00065   coefficient = 2.5;
00066   period = 10;
00067   no_decline_period = 2;
00068   method = "Long";
00069   label = pluginName;
00070 }
00071 
00072 Indicator * SZ::calculate ()
00073 {
00074   Indicator *output = new Indicator;
00075   output->setDateFlag(dateFlag);
00076   output->setLogScale(logScale);
00077   output->addLine(getSZ());
00078   return output;
00079 }
00080 
00081 PlotLine * SZ::getSZ ()
00082 {
00083   if (period < 1)
00084     period = 1;
00085 
00086   int display_uptrend = 0;
00087   int display_dntrend = 0;
00088   int position = 1;
00089   if (! method.compare("Long"))
00090     position = 1;
00091   else
00092     position = 2;
00093   if (position & 1) // long
00094     display_uptrend = 1;
00095   if (position & 2) // short
00096     display_dntrend = 1;
00097 
00098   PlotLine *sz_uptrend = new PlotLine();
00099   PlotLine *sz_dntrend = new PlotLine();
00100 
00101   double uptrend_stop = 0;
00102   double dntrend_stop = 0;
00103 
00104   if (no_decline_period < 0)
00105     no_decline_period = 0;
00106   if (no_decline_period > 365)
00107     no_decline_period = 365;
00108 
00109   double old_uptrend_stops[no_decline_period];
00110   double old_dntrend_stops[no_decline_period];
00111 
00112   int loop;
00113   for (loop = 0; loop < no_decline_period; loop++)
00114   {
00115     old_uptrend_stops[loop] = 0;
00116     old_dntrend_stops[loop] = 0;
00117   }
00118 
00119   int start = period + 1;
00120   for (loop = start; loop < (int) data->count(); loop++)
00121   {
00122     // calculate downside/upside penetration for lookback period
00123     int lbloop;
00124     int lbstart = loop - period;
00125     if (lbstart < 2)
00126       lbstart = 2;
00127     double uptrend_noise_avg = 0;
00128     double uptrend_noise_cnt = 0;
00129     double dntrend_noise_avg = 0;
00130     double dntrend_noise_cnt = 0;
00131     for (lbloop = lbstart; lbloop < loop; lbloop++)
00132     {
00133       double lo_curr = data->getLow(lbloop);
00134       double lo_last = data->getLow(lbloop - 1);
00135       double hi_curr = data->getHigh(lbloop);
00136       double hi_last = data->getHigh(lbloop - 1);
00137       if (lo_last > lo_curr)
00138       {
00139         uptrend_noise_avg += lo_last - lo_curr;
00140         uptrend_noise_cnt++;
00141       }
00142       if (hi_last < hi_curr)
00143       {
00144         dntrend_noise_avg += hi_curr - hi_last;
00145         dntrend_noise_cnt++;
00146       }
00147     }
00148     // make *_avg into actual averages
00149     if (uptrend_noise_cnt > 0)
00150       uptrend_noise_avg /= uptrend_noise_cnt;
00151     if (dntrend_noise_cnt > 0)
00152       dntrend_noise_avg /= dntrend_noise_cnt;
00153 
00154     double lo_last = data->getLow(loop - 1);
00155     double hi_last = data->getHigh(loop - 1);
00156     uptrend_stop = lo_last - coefficient * uptrend_noise_avg;
00157     dntrend_stop = hi_last + coefficient * dntrend_noise_avg;
00158 
00159     double adjusted_uptrend_stop = uptrend_stop;
00160     double adjusted_dntrend_stop = dntrend_stop;
00161 
00162     int backloop;
00163     for (backloop = no_decline_period - 1; backloop >= 0; backloop--)
00164     {
00165       if (loop - backloop > start)
00166       {
00167         if (old_uptrend_stops[backloop] > adjusted_uptrend_stop)
00168           adjusted_uptrend_stop = old_uptrend_stops[backloop];
00169         if (old_dntrend_stops[backloop] < adjusted_dntrend_stop)
00170           adjusted_dntrend_stop = old_dntrend_stops[backloop];
00171       }
00172       if (backloop > 0)
00173       {
00174         old_uptrend_stops[backloop] = old_uptrend_stops[backloop-1];
00175         old_dntrend_stops[backloop] = old_dntrend_stops[backloop-1];
00176       }
00177     }
00178 
00179     old_uptrend_stops[0] = uptrend_stop;
00180     old_dntrend_stops[0] = dntrend_stop;
00181 
00182     sz_uptrend->append(adjusted_uptrend_stop);
00183     sz_dntrend->append(adjusted_dntrend_stop);
00184   }
00185 
00186   PlotLine *pl = 0;
00187   if (display_uptrend)
00188   {
00189     sz_uptrend->setColor(color);
00190     sz_uptrend->setType(lineType);
00191     QString t = QObject::tr("SZ LONG");
00192     sz_uptrend->setLabel(t);
00193     pl = sz_uptrend;
00194   }
00195 
00196   if (display_dntrend)
00197   {
00198     sz_dntrend->setColor(color);
00199     sz_dntrend->setType(lineType);
00200     QString t = QObject::tr("SZ SHORT");
00201     sz_dntrend->setLabel(t);
00202     pl = sz_dntrend;
00203   }
00204 
00205   return pl;
00206 }
00207 
00208 int SZ::indicatorPrefDialog (QWidget *w)
00209 {
00210   QString pl = QObject::tr("Parms");
00211   QString cl = QObject::tr("Color");
00212   QString ll = QObject::tr("Label");
00213   QString ltl = QObject::tr("Line Type");
00214   QString pos = QObject::tr("Position");
00215   QString lp = QObject::tr("Lookback Period");
00216   QString ndp = QObject::tr("No Decline Period");
00217   QString co = QObject::tr("Coefficient");
00218   
00219   PrefDialog *dialog = new PrefDialog(w);
00220   dialog->setCaption(QObject::tr("SZ Indicator"));
00221   dialog->createPage (pl);
00222   dialog->setHelpFile(helpFile);
00223   dialog->addColorItem(cl, pl, color);
00224   dialog->addComboItem(ltl, pl, lineTypes, lineType);
00225   dialog->addComboItem(pos, pl, methodList, method);
00226   dialog->addIntItem(lp, pl, period, 1, 99999999);
00227   dialog->addIntItem(ndp, pl, no_decline_period, 1, 99999999);
00228   dialog->addDoubleItem(co, pl, coefficient, 0, 99999999);
00229   dialog->addTextItem(ll, pl, label);
00230   
00231   int rc = dialog->exec();
00232   
00233   if (rc == QDialog::Accepted)
00234   {
00235     dialog->getColor(cl, color);
00236     lineType = (PlotLine::LineType) dialog->getComboIndex(ltl);
00237     period = dialog->getInt(lp);
00238     no_decline_period = dialog->getInt(ndp);
00239     coefficient = dialog->getDouble(co);
00240     dialog->getCombo(pos, method);
00241     dialog->getText(ll, label);
00242     rc = TRUE;
00243   }
00244   else
00245     rc = FALSE;
00246   
00247   delete dialog;
00248   return rc;
00249 }
00250 
00251 void SZ::setIndicatorSettings (Setting &dict)
00252 {
00253   setDefaults();
00254   
00255   if (! dict.count())
00256     return;
00257   
00258   QString s;
00259   dict.getData(colorLabel, s);
00260   if (s.length())
00261     color.setNamedColor(s);
00262     
00263   dict.getData(lineTypeLabel, s);
00264   if (s.length())
00265     lineType = (PlotLine::LineType) s.toInt();
00266 
00267   dict.getData(periodLabel, s);
00268   if (s.length())
00269     period = s.toInt();
00270 
00271   dict.getData(noDeclinePeriodLabel, s);
00272   if (s.length())
00273     no_decline_period = s.toInt();
00274 
00275   dict.getData(coefficientLabel, s);
00276   if (s.length())
00277     coefficient = s.toFloat();
00278 
00279   dict.getData(methodLabel, s);
00280   if (s.length())
00281     method = s;
00282 
00283   dict.getData(labelLabel, s);
00284   if (s.length())
00285     label = s;
00286 }
00287 
00288 void SZ::getIndicatorSettings (Setting &dict)
00289 {
00290   QString ts = color.name();
00291   dict.setData(colorLabel, ts);
00292   ts = QString::number(lineType);
00293   dict.setData(lineTypeLabel, ts);
00294   ts = QString::number(period);
00295   dict.setData(periodLabel, ts);
00296   ts = QString::number(no_decline_period);
00297   dict.setData(noDeclinePeriodLabel, ts);
00298   ts = QString::number(coefficient);
00299   dict.setData(coefficientLabel, ts);
00300   dict.setData(methodLabel, method);
00301   dict.setData(labelLabel, label);
00302   dict.setData(pluginLabel, pluginName);
00303 }
00304 
00305 PlotLine * SZ::calculateCustom (QString &p, QPtrList<PlotLine> &d)
00306 {
00307   // format1: METHOD, PERIOD, NO_DECLINE_PERIOD, COEFFICIENT
00308 
00309   if (checkFormat(p, d, 4, 4))
00310     return 0;
00311 
00312   if (methodList.findIndex(formatStringList[0]) == -1)
00313   {
00314     qDebug("SZ::calculateCustom: invalid METHOD parm");
00315     return 0;
00316   }
00317 
00318   method = formatStringList[0];
00319   period = formatStringList[1].toInt();
00320   no_decline_period = formatStringList[2].toInt();
00321   coefficient = formatStringList[3].toDouble();
00322 
00323   return getSZ();
00324 }
00325 
00326 void SZ::formatDialog (QStringList &, QString &rv, QString &rs)
00327 {
00328   rs.truncate(0);
00329   rv.truncate(0);
00330   QString pl = QObject::tr("Parms");
00331   QString vnl = QObject::tr("Variable Name");
00332   QString pos = QObject::tr("Position");
00333   QString lp = QObject::tr("Lookback Period");
00334   QString ndp = QObject::tr("No Decline Period");
00335   QString co = QObject::tr("Coefficient");
00336   PrefDialog *dialog = new PrefDialog(0);
00337   dialog->setCaption(QObject::tr("SZ Format"));
00338   dialog->createPage (pl);
00339   dialog->setHelpFile(helpFile);
00340 
00341   QString s;
00342   dialog->addTextItem(vnl, pl, s);
00343   dialog->addComboItem(pos, pl, methodList, method);
00344   dialog->addIntItem(lp, pl, period, 1, 99999999);
00345   dialog->addIntItem(ndp, pl, no_decline_period, 1, 99999999);
00346   dialog->addDoubleItem(co, pl, coefficient, 0, 99999999);
00347 
00348   int rc = dialog->exec();
00349   
00350   if (rc == QDialog::Accepted)
00351   {
00352     dialog->getText(vnl, rv);
00353 
00354     dialog->getCombo(pos, rs);
00355 
00356     int t = dialog->getInt(lp);
00357     rs.append("," + QString::number(t));
00358 
00359     t = dialog->getInt(ndp);
00360     rs.append("," + QString::number(t));
00361 
00362     double d = dialog->getDouble(co);
00363     rs.append("," + QString::number(d));
00364   }
00365 
00366   delete dialog;
00367 }
00368