lib/StocksDialog.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 "StocksDialog.h"
00023 #include "Bar.h"
00024 #include "HelpWindow.h"
00025 #include "DBIndexItem.h"
00026 #include "COBase.h"
00027 #include "Exchange.h"
00028 #include "RcFile.h"
00029 #include <qsize.h>
00030 #include <qlabel.h>
00031 #include <qlayout.h>
00032 #include <qmessagebox.h>
00033 #include <qfileinfo.h>
00034 
00035 StocksDialog::StocksDialog (QString p, DbPlugin *d, DBIndex *i) : QTabDialog (0, "StocksDialog", TRUE)
00036 {
00037   helpFile = p;
00038   db = d;
00039   index = i;
00040   reloadFlag = FALSE;
00041   currentDate = QDateTime::currentDateTime();
00042 
00043   setCaption(tr("Qtstalker: Edit Stock"));
00044 
00045   QString s;
00046   d->getSymbol(s);
00047   QFileInfo fi(s);
00048   symbol = fi.fileName();
00049   
00050   createDetailsPage();
00051   createDataPage();
00052   createFundamentalsPage();
00053   createSplitPage();
00054   
00055   setOkButton(tr("&OK"));
00056   setCancelButton(tr("&Cancel"));
00057   connect(this, SIGNAL(applyButtonPressed()), this, SLOT(saveChart()));
00058   
00059   setHelpButton();
00060   QObject::connect(this, SIGNAL(helpButtonPressed()), this, SLOT(help()));
00061   
00062   RcFile rcfile;
00063   QSize sz;
00064   rcfile.loadSize(RcFile::EditStockWindowSize, sz);
00065   resize(sz);
00066 }
00067 
00068 StocksDialog::~StocksDialog ()
00069 {
00070   RcFile rcfile;
00071   rcfile.saveSize(RcFile::EditStockWindowSize, size());
00072 }
00073 
00074 void StocksDialog::createDetailsPage ()
00075 {
00076   QWidget *w = new QWidget(this);
00077   
00078   QVBoxLayout *vbox = new QVBoxLayout(w);
00079   vbox->setMargin(5);
00080   vbox->setSpacing(5);
00081     
00082   QGridLayout *grid = new QGridLayout(vbox);
00083   grid->setMargin(0);
00084   grid->setSpacing(5);
00085   
00086   QLabel *label = new QLabel(tr("Symbol"), w);
00087   grid->addWidget(label, 0, 0);
00088 
00089   QString s;
00090   DBIndexItem item;
00091   index->getIndexItem(symbol, item);
00092   item.getSymbol(s);
00093   label = new QLabel(s, w);
00094   label->setFrameStyle(QFrame::WinPanel | QFrame::Sunken);
00095   grid->addWidget(label, 0, 1);
00096 
00097   label = new QLabel(tr("Name"), w);
00098   grid->addWidget(label, 1, 0);
00099 
00100   item.getTitle(s);  
00101   title = new QLineEdit(s, w);
00102   grid->addWidget(title, 1, 1);
00103   
00104   label = new QLabel(tr("Exchange"), w);
00105   grid->addWidget(label, 2, 0);
00106 
00107   item.getExchange(s);  
00108   Exchange ex;
00109   ex.getExchange(s.toInt(), s);
00110   label = new QLabel(s, w);
00111   label->setFrameStyle(QFrame::WinPanel | QFrame::Sunken);
00112   grid->addWidget(label, 2, 1);
00113 
00114   label = new QLabel(tr("Type"), w);
00115   grid->addWidget(label, 3, 0);
00116 
00117   item.getType(s);  
00118   label = new QLabel(s, w);
00119   label->setFrameStyle(QFrame::WinPanel | QFrame::Sunken);
00120   grid->addWidget(label, 3, 1);
00121   
00122   label = new QLabel(tr("First Date"), w);
00123   grid->addWidget(label, 4, 0);
00124   
00125   Bar bar;
00126   db->getFirstBar(bar);
00127   if (! bar.getEmptyFlag())
00128   {
00129     bar.getDateTimeString(TRUE, s);
00130     label = new QLabel(s, w);
00131     label->setFrameStyle(QFrame::WinPanel | QFrame::Sunken);
00132     grid->addWidget(label, 4, 1);
00133   }
00134   
00135   label = new QLabel(tr("Last Date"), w);
00136   grid->addWidget(label, 5, 0);
00137   
00138   Bar bar2;
00139   db->getLastBar(bar2);
00140   if (! bar2.getEmptyFlag())
00141   {
00142     bar2.getDateTimeString(TRUE, s);
00143     label = new QLabel(s, w);
00144     label->setFrameStyle(QFrame::WinPanel | QFrame::Sunken);
00145     grid->addWidget(label, 5, 1);
00146   }
00147   
00148   grid->expand(grid->numRows() + 1, grid->numCols());
00149   grid->setColStretch(1, 1);
00150   
00151   vbox->addStretch(1);
00152 
00153   addTab(w, tr("Details"));  
00154 }
00155 
00156 void StocksDialog::createDataPage ()
00157 {
00158   QWidget *w = new QWidget(this);
00159     
00160   QVBoxLayout *vbox = new QVBoxLayout(w);
00161   vbox->setMargin(5);
00162   vbox->setSpacing(0);
00163 
00164   barEdit = new BarEdit(w);
00165   QString s = tr("Open");  
00166   QString s2 = "Open";  
00167   barEdit->createField(s, s2, FALSE);
00168   s = tr("High");  
00169   s2 = "High";  
00170   barEdit->createField(s, s2, FALSE);
00171   s = tr("Low");  
00172   s2 = "Low";  
00173   barEdit->createField(s, s2, FALSE);
00174   s = tr("Close");  
00175   s2 = "Close";  
00176   barEdit->createField(s, s2, FALSE);
00177   s = tr("Volume");  
00178   s2 = "Volume";  
00179   barEdit->createField(s, s2, FALSE);
00180   connect(barEdit, SIGNAL(signalDeleteRecord()), this, SLOT(deleteRecord()));
00181   connect(barEdit, SIGNAL(signalSaveRecord()), this, SLOT(saveRecord()));
00182   connect(barEdit, SIGNAL(signalSearch(QDateTime)), this, SLOT(slotDateSearch(QDateTime)));
00183   connect(barEdit, SIGNAL(signalFirstRecord()), this, SLOT(slotFirstRecord()));
00184   connect(barEdit, SIGNAL(signalLastRecord()), this, SLOT(slotLastRecord()));
00185   connect(barEdit, SIGNAL(signalPrevRecord()), this, SLOT(slotPrevRecord()));
00186   connect(barEdit, SIGNAL(signalNextRecord()), this, SLOT(slotNextRecord()));
00187   vbox->addWidget(barEdit);
00188   
00189   addTab(w, tr("Data"));  
00190 }
00191 
00192 void StocksDialog::createFundamentalsPage ()
00193 {
00194   QWidget *w = new QWidget(this);
00195   
00196   QVBoxLayout *vbox = new QVBoxLayout(w);
00197   vbox->setMargin(5);
00198   vbox->setSpacing(5);
00199     
00200   Setting fund;
00201   QString s, s2;
00202   index->getFundamentals(symbol, s2); 
00203   fund.parse(s2);
00204   
00205   s = tr("Fundamentals: last updated ");
00206   s2 = "updateDate";
00207   QString s3;
00208   fund.getData(s2, s3);
00209   s.append(s3);
00210   fund.remove(s2);
00211   QStringList key;
00212   fund.getKeyList(key);
00213   key.sort();
00214   
00215   vbox->addSpacing(10);
00216   QLabel *label = new QLabel(s, w);
00217   vbox->addWidget(label);
00218   
00219   fundView = new QListView(w);
00220   fundView->addColumn(tr("Description"));
00221   fundView->addColumn(tr("Value"));
00222   vbox->addWidget(fundView);
00223   
00224   int loop;
00225   for (loop = 0; loop < (int) key.count(); loop++)
00226   {
00227     fund.getData(key[loop], s);
00228     new QListViewItem(fundView, key[loop], s);
00229   }
00230   
00231   if (! key.count())
00232     new QListViewItem(fundView, tr("No data available."));
00233     
00234   addTab(w, tr("Fundamentals"));  
00235 }
00236 
00237 void StocksDialog::createSplitPage ()
00238 {
00239   QWidget *w = new QWidget(this);
00240     
00241   QVBoxLayout *vbox = new QVBoxLayout(w);
00242   vbox->setMargin(5);
00243   vbox->setSpacing(5);
00244 
00245   QGridLayout *grid = new QGridLayout(vbox);
00246   grid->setMargin(0);
00247   grid->setSpacing(5);
00248   
00249   QLabel *label = new QLabel(tr("Split Date"), w);
00250   grid->addWidget(label, 0, 0);
00251 
00252   Bar bar;
00253   db->getLastBar(bar);
00254   QDateTime dt;
00255   bar.getDate(dt);
00256   if (! bar.getEmptyFlag())
00257     splitDate = new QDateEdit(dt.date(), w);
00258   else
00259     splitDate = new QDateEdit(QDate::currentDate(), w);
00260   splitDate->setOrder(QDateEdit::YMD);
00261   grid->addWidget(splitDate, 0, 1);
00262 
00263   label = new QLabel(tr("Split Ratio"), w);
00264   grid->addWidget(label, 1, 0);
00265   
00266   splitRatio = new QLineEdit("2:1", w);
00267   grid->addWidget(splitRatio, 1, 1);
00268 
00269   QPushButton *button = new QPushButton(tr("Perform Split"), w);
00270   connect(button, SIGNAL(clicked()), this, SLOT(split()));
00271   vbox->addWidget(button);
00272 
00273   vbox->addStretch(1);
00274   
00275   addTab(w, tr("Split"));  
00276 }
00277 
00278 void StocksDialog::deleteRecord ()
00279 {
00280   Bar bar;
00281   QString s;
00282   barEdit->getDate(s);
00283   if (bar.setDate(s))
00284     return;
00285   bar.getDateTimeString(FALSE, s);
00286   db->deleteData(s);
00287 
00288   reloadFlag = TRUE;
00289 }
00290 
00291 void StocksDialog::saveRecord ()
00292 {
00293   Bar bar;
00294   QString s, s2;
00295   barEdit->getDate(s);
00296   bar.setDate(s);
00297 
00298   s = "Open";
00299   barEdit->getField(s, s2);
00300   bar.setOpen(s2.toDouble());
00301 
00302   s = "High";
00303   barEdit->getField(s, s2);
00304   bar.setHigh(s2.toDouble());
00305 
00306   s = "Low";
00307   barEdit->getField(s, s2);
00308   bar.setLow(s2.toDouble());
00309 
00310   s = "Close";
00311   barEdit->getField(s, s2);
00312   bar.setClose(s2.toDouble());
00313 
00314   s = "Volume";
00315   barEdit->getField(s, s2);
00316   bar.setVolume(s2.toDouble());
00317   db->setBar(bar);
00318 
00319   reloadFlag = TRUE;
00320 }
00321 
00322 void StocksDialog::slotDateSearch (QDateTime dt)
00323 {
00324   Bar record;
00325   db->getSearchBar(dt, record);
00326   if (record.getEmptyFlag())
00327     return;
00328   updateFields(record);
00329 }
00330 
00331 void StocksDialog::saveChart ()
00332 {
00333   QString s = title->text();
00334   DBIndexItem item;
00335   index->getIndexItem(symbol, item);
00336   item.setTitle(s);
00337   index->setIndexItem(symbol, item);
00338 
00339   if (barEdit->getSaveFlag())
00340   {  
00341     int rc = QMessageBox::warning(this,
00342                                   tr("Warning"),
00343                                   tr("Record has been modified.\nSave changes?"),
00344                                   QMessageBox::Yes,
00345                                   QMessageBox::No,
00346                                   QMessageBox::NoButton);
00347 
00348     if (rc == QMessageBox::Yes)
00349       saveRecord();
00350   }
00351 
00352   reloadFlag = TRUE;
00353   accept();
00354 }
00355 
00356 void StocksDialog::help ()
00357 {
00358   HelpWindow *hw = new HelpWindow(this, helpFile);
00359   hw->show();
00360 }
00361 
00362 void StocksDialog::split ()
00363 {
00364   int rc = QMessageBox::warning(this,
00365                                 tr("Warning"),
00366                                 tr("Are you sure you want split the stock?"),
00367                                 QMessageBox::Yes,
00368                                 QMessageBox::No,
00369                                 QMessageBox::NoButton);
00370 
00371   if (rc == QMessageBox::No)
00372     return;
00373 
00374   QDate dt = splitDate->date();
00375   
00376   // verify if split date < first bar
00377   Bar bar;
00378   db->getFirstBar(bar);
00379   if (! bar.getEmptyFlag())
00380   {
00381     QDateTime td;
00382     bar.getDate(td);
00383     if (dt < td.date())
00384     {
00385       QMessageBox::information(this, tr("Qtstalker: Error"), tr("Invalid split date."));
00386       return;
00387     }
00388   }
00389 
00390   // verify if split date > last bar
00391   Bar bar2;
00392   db->getLastBar(bar2);
00393   if (! bar.getEmptyFlag())
00394   {
00395     QDateTime td;
00396     bar2.getDate(td);
00397     if (dt > td.date())
00398     {
00399       QMessageBox::information(this, tr("Qtstalker: Error"), tr("Invalid split date."));
00400       return;
00401     }
00402   }
00403 
00404   // verify if the ratio format is correct ?:?
00405   QStringList l = QStringList::split(":", splitRatio->text(), FALSE);
00406   if (l.count() != 2)
00407   {
00408     QMessageBox::information(this, tr("Qtstalker: Error"), tr("Invalid split ratio format.\neg. 2:1"));
00409     return;
00410   }
00411 
00412   double plyer = l[1].toDouble() / l[0].toDouble();
00413   double volplyer = l[0].toDouble() / l[1].toDouble();
00414 
00415   QString s;
00416   db->getSymbol(s);
00417   BarData *bars = new BarData(s);
00418   db->getAllBars(bars);
00419 
00420   int loop;
00421   for (loop = 0; loop < bars->count(); loop++)
00422   {
00423     Bar bar;
00424     bars->getBar(loop, bar);
00425 
00426     QDateTime td;
00427     bar.getDate(td);
00428     if (td.date() < dt)
00429     {
00430       bar.setOpen(bar.getOpen() * plyer);
00431       bar.setHigh(bar.getHigh() * plyer);
00432       bar.setLow(bar.getLow() * plyer);
00433       bar.setClose(bar.getClose() * plyer);
00434       bar.setVolume(bar.getVolume() * volplyer);
00435       db->setBar(bar);
00436     }
00437   }
00438 
00439   delete bars;
00440 
00441   // adjust any chart objects
00442   QDateTime adt(dt, QTime(0,0,0,0));
00443   QString fn;
00444   db->getIndexKey(fn);
00445   index->getChartObjects(fn, l);
00446   for (loop = 0; loop < (int) l.count(); loop++)
00447   {
00448     Setting set;
00449     set.parse(l[loop]);
00450     COBase tco;
00451     COBase *co = tco.getCO(set);
00452     if (! co)
00453       continue;
00454 
00455     co->adjustForSplit(adt, plyer);
00456 
00457     set.clear();
00458     co->getSettings(set);
00459     s = "Name";
00460     QString s2;
00461     set.getData(s, s2);
00462     index->setChartObject(fn, s2, set);
00463   }
00464   
00465   QMessageBox::information(this, tr("Qtstalker: Split Complete"), tr("Split complete."));
00466 
00467   reloadFlag = TRUE;
00468 }
00469 
00470 void StocksDialog::slotFirstRecord ()
00471 {
00472   Bar record;
00473   db->getFirstBar(record);
00474   if (record.getEmptyFlag())
00475     return;
00476   updateFields(record);
00477 }
00478 
00479 void StocksDialog::slotLastRecord ()
00480 {
00481   Bar record;
00482   db->getLastBar(record);
00483   if (record.getEmptyFlag())
00484     return;
00485   updateFields(record);
00486 }
00487 
00488 void StocksDialog::slotNextRecord ()
00489 {
00490   Bar record;
00491   db->getNextBar(currentDate, record);
00492   if (record.getEmptyFlag())
00493     return;
00494   updateFields(record);
00495 }
00496 
00497 void StocksDialog::slotPrevRecord ()
00498 {
00499   Bar record;
00500   db->getPrevBar(currentDate, record);
00501   if (record.getEmptyFlag())
00502     return;
00503   updateFields(record);
00504 }
00505 
00506 void StocksDialog::updateFields (Bar &record)
00507 {
00508   record.getDate(currentDate);
00509 
00510   QString s;
00511   record.getDateTimeString(TRUE, s);
00512   barEdit->setDate(s, record.getTickFlag());
00513   
00514   s = "Open";
00515   QString s2 = QString::number(record.getOpen());
00516   barEdit->setField(s, s2);
00517   
00518   s = "High";
00519   s2 = QString::number(record.getHigh());
00520   barEdit->setField(s, s2);
00521   
00522   s = "Low";
00523   s2 = QString::number(record.getLow());
00524   barEdit->setField(s, s2);
00525   
00526   s = "Close";
00527   s2 = QString::number(record.getClose());
00528   barEdit->setField(s, s2);
00529   
00530   s = "Volume";
00531   s2 = QString::number(record.getVolume(), 'f', 0);
00532   barEdit->setField(s, s2);
00533 
00534   barEdit->clearButtons();
00535 }
00536 
00537 bool StocksDialog::getReloadFlag ()
00538 {
00539   return reloadFlag;
00540 }
00541