src/PortfolioDialog.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 "PortfolioDialog.h"
00023 #include "Setting.h"
00024 #include "FuturesData.h"
00025 #include "PrefDialog.h"
00026 #include "DbPlugin.h"
00027 #include "HelpWindow.h"
00028 #include "DBIndexItem.h"
00029 #include "../pics/newchart.xpm"
00030 #include "../pics/edit.xpm"
00031 #include "../pics/delete.xpm"
00032 #include <qstringlist.h>
00033 #include <qmessagebox.h>
00034 #include <qdir.h>
00035 #include <qfile.h>
00036 #include <qtextstream.h>
00037 #include <qlayout.h>
00038 
00039 PortfolioDialog::PortfolioDialog (QString p, DBIndex *i) : QTabDialog (0, "PortfolioDialog", TRUE)
00040 {
00041   portfolio = p;
00042   index = i;
00043 
00044   QString s = tr("Qtstalker: Portfolio") + " " + portfolio;
00045   setCaption(s);
00046 
00047   QWidget *w = new QWidget(this);
00048     
00049   QVBoxLayout *vbox = new QVBoxLayout(w);
00050   vbox->setMargin(5);
00051   vbox->setSpacing(0);
00052 
00053   toolbar = new Toolbar(w, Toolbar::Horizontal);
00054   vbox->addWidget(toolbar);
00055   vbox->addSpacing(10);
00056   
00057   connect(this, SIGNAL(applyButtonPressed()), this, SLOT(savePortfolio()));
00058 
00059   s = "add";
00060   QString s2(tr("Add"));
00061   toolbar->addButton(s, QPixmap(newchart), s2);
00062   connect(toolbar->getButton(s), SIGNAL(clicked()), this, SLOT(addItem()));
00063   toolbar->getButton(s)->setAccel(CTRL+Key_A);
00064 
00065   s = "edit";
00066   s2 = tr("Edit");
00067   toolbar->addButton(s, QPixmap(edit), s2);
00068   connect(toolbar->getButton(s), SIGNAL(clicked()), this, SLOT(modifyItem()));
00069   toolbar->setButtonStatus(s, FALSE);
00070   toolbar->getButton(s)->setAccel(CTRL+Key_E);
00071 
00072   s = "delete";
00073   s2 = tr("Delete");
00074   toolbar->addButton(s, QPixmap(deleteitem), s2);
00075   connect(toolbar->getButton(s), SIGNAL(clicked()), this, SLOT(deleteItem()));
00076   toolbar->setButtonStatus(s, FALSE);
00077   toolbar->getButton(s)->setAccel(CTRL+Key_D);
00078 
00079   plist = new QListView(w);
00080   plist->setSelectionMode(QListView::Single);
00081   plist->addColumn(tr("Symbol"), -1);
00082   plist->addColumn(tr("L/S"), -1);
00083   plist->addColumn(tr("Vol"), -1);
00084   plist->addColumn(tr("Buy"), -1);
00085   plist->addColumn(tr("Last Date"), -1);
00086   plist->addColumn(tr("Value"), -1);
00087   plist->addColumn(tr("Profit"), -1);
00088   plist->addColumn(tr("Profit%"), -1);
00089   connect(plist, SIGNAL(clicked(QListViewItem *)), this, SLOT(buttonStatus(QListViewItem *)));
00090   connect(plist, SIGNAL(doubleClicked(QListViewItem *, const QPoint &, int)), this,
00091           SLOT(itemDoubleClicked(QListViewItem *, const QPoint &, int)));
00092   vbox->insertWidget(2, plist);
00093   
00094   QHBoxLayout *hbox = new QHBoxLayout(vbox);
00095   
00096   balance = new QLabel(w);
00097   hbox->addWidget(balance);
00098   
00099   addTab(w, tr("Details"));
00100   
00101   setCancelButton();
00102   
00103   setHelpButton();
00104   QObject::connect(this, SIGNAL(helpButtonPressed()), this, SLOT(slotHelp()));
00105 
00106   buttonStatus(0);
00107 
00108   updatePortfolio();
00109 }
00110 
00111 PortfolioDialog::~PortfolioDialog ()
00112 {
00113 }
00114 
00115 void PortfolioDialog::updatePortfolio ()
00116 {
00117   plist->clear();
00118 
00119   QString s;
00120   config.getData(Config::PortfolioPath, s);
00121   s.append("/" + portfolio);
00122 
00123   QFile f(s);
00124   if (! f.open(IO_ReadOnly))
00125     return;
00126   QTextStream stream(&f);
00127   while(stream.atEnd() == 0)
00128   {
00129     s = stream.readLine();
00130     s = s.stripWhiteSpace();
00131     if (s.length())
00132     {
00133       QStringList l = QStringList::split(",", s, FALSE);
00134 
00135       s = l[0];
00136       if (s.contains("/"))
00137       {
00138         QFileInfo fi(s);
00139         s = fi.fileName();
00140       }
00141       item = new QListViewItem(plist, s, l[1], l[2], l[3]);
00142     }
00143   }
00144 
00145   f.close();
00146 
00147   updatePortfolioItems();
00148 }
00149 
00150 void PortfolioDialog::updatePortfolioItems ()
00151 {
00152   double bal = 0;
00153   double orig = 0;
00154   
00155   QListViewItemIterator it(plist);
00156   for (; it.current(); ++it)
00157   {
00158     item = it.current();
00159 
00160     QString symbol = item->text(0);
00161     QString action = item->text(1);
00162     QString volume = item->text(2);
00163     QString price = item->text(3);
00164 
00165     DBIndexItem hitem;
00166     index->getIndexItem(symbol, hitem);
00167     QString s;
00168     hitem.getPath(s);
00169     QDir dir(s);
00170     if (! dir.exists(s, TRUE))
00171       continue;
00172 
00173     DbPlugin plug;
00174     if (plug.open(s, index))
00175       continue;
00176 
00177     QString type;
00178     hitem.getType(type);
00179     
00180     QString futuresType;
00181     hitem.getFuturesType(futuresType);
00182     
00183     Bar bar;
00184     plug.getLastBar(bar);
00185     
00186     if (bar.getEmptyFlag())
00187     {
00188       plug.close();
00189       continue;
00190     }
00191     
00192     bar.getDateTimeString(TRUE, s);
00193     item->setText(4, s);
00194 
00195     QString last = QString::number(bar.getClose());
00196     item->setText(5, last);
00197 
00198     double total;
00199     if (! action.compare(tr("Long")))
00200       total = volume.toDouble() * (last.toDouble() - price.toDouble());
00201     else
00202       total = volume.toDouble() * (price.toDouble() - last.toDouble());
00203 
00204     if (! type.compare("Futures"))
00205       total = futuresProfit(futuresType, total);
00206 
00207     item->setText(6, QString::number(total));
00208     
00209     double spent = price.toDouble() * volume.toDouble() * (action.compare(tr("Long"))?-1:1);
00210 
00211     if (total == 0)
00212       item->setText(7, "0%");
00213     else if (spent == 0)
00214       item->setText(7, "");
00215     else
00216       item->setText(7, QString::number((total / spent) * 100, 'f', 2) + "%");
00217 
00218     bal += total;
00219     orig += spent;
00220     
00221     plug.close();
00222   }
00223 
00224   if (bal == 0 || orig == 0)
00225     balance->setText(tr("Balance: ") + QString::number(bal) + " (0%)");
00226   else  
00227     balance->setText(tr("Balance: ") + QString::number(bal) + 
00228                      " (" + QString::number((bal / orig) * 100, 'f', 2) + "%)");
00229 }
00230 
00231 void PortfolioDialog::savePortfolio ()
00232 {
00233   QString s;
00234   config.getData(Config::PortfolioPath, s);
00235   s.append("/" + portfolio);
00236   QFile f(s);
00237   if (! f.open(IO_WriteOnly))
00238     return;
00239   QTextStream stream(&f);
00240 
00241   QListViewItemIterator it(plist);
00242   for (; it.current(); ++it)
00243   {
00244     item = it.current();
00245     s = item->text(0) + "," + item->text(1) + "," + item->text(2) + "," + item->text(3);
00246     stream << s << "\n";
00247   }
00248 
00249   f.close();
00250 
00251   reject();
00252 }
00253 
00254 void PortfolioDialog::addItem ()
00255 {
00256   PrefDialog *dialog = new PrefDialog;
00257   dialog->setCaption(tr("New Portfolio Item"));
00258   
00259   QString pl = tr("Details");
00260   QString sl = tr("Symbol");
00261   QString al = tr("Action");
00262   QString prl = tr("Price");
00263   QString vl = tr("Volume");
00264   
00265   dialog->createPage(pl);
00266   
00267   QString dpath;
00268   config.getData(Config::DataPath, dpath);
00269   QString s;
00270   dialog->addSymbolItem(sl, pl, dpath, s);
00271 
00272   QStringList l;
00273   l.append(tr("Long"));
00274   l.append(tr("Short"));
00275   dialog->addComboItem(al, pl, l, l[0]);
00276   
00277   dialog->addDoubleItem(prl, pl, 0, 0, 9999999999.0);
00278   
00279   dialog->addDoubleItem(vl, pl, 1, 1, 99999999);
00280   
00281   int rc = dialog->exec();
00282   
00283   if (rc == QDialog::Accepted)
00284   {
00285     QString symbol;
00286     dialog->getSymbol(sl, symbol);
00287     if (symbol.isNull())
00288       QMessageBox::information(this, tr("Qtstalker: Error"), tr("No symbol selected."));
00289     else
00290     {
00291       QString action;
00292       dialog->getCombo(al, action);
00293       double vol = dialog->getDouble(vl);
00294       double price = dialog->getDouble(prl);
00295       QFileInfo fi(symbol);
00296       new QListViewItem(plist, fi.fileName(), action, QString::number(vol), QString::number(price));
00297 
00298       updatePortfolioItems();
00299     }
00300   }
00301 
00302   delete dialog;
00303 }
00304 
00305 void PortfolioDialog::deleteItem ()
00306 {
00307   item = plist->selectedItem();
00308   if (item)
00309   {
00310     QListViewItemIterator it(plist);
00311     int count = 0;
00312     for (; it.current(); ++it)
00313     {
00314       if (it.current()->text(0) == item->text(0))
00315         count++;
00316     }
00317     delete item;
00318   }
00319 
00320   updatePortfolioItems();
00321 
00322   buttonStatus(0);
00323 }
00324 
00325 void PortfolioDialog::modifyItem ()
00326 {
00327   item = plist->currentItem();
00328   if (! item)
00329     return;
00330 
00331   PrefDialog *dialog = new PrefDialog;
00332   dialog->setCaption(tr("Edit Portfolio Item"));
00333   
00334   QString pl = tr("Details");
00335   QString sl = tr("Symbol");
00336   QString al = tr("Action");
00337   QString prl = tr("Price");
00338   QString vl = tr("Volume");
00339   
00340   dialog->createPage(pl);
00341 
00342   QString dpath;
00343   config.getData(Config::DataPath, dpath);
00344 
00345   QString ts = item->text(0);
00346   DBIndexItem iitem;
00347   index->getIndexItem(ts, iitem);
00348   QString ts2, s;
00349   iitem.getPath(ts2);
00350 
00351   dialog->addSymbolItem(sl, pl, dpath, ts2);
00352 
00353   QStringList l;
00354   l.append(tr("Long"));
00355   l.append(tr("Short"));
00356   s = item->text(1);
00357   dialog->addComboItem(al, pl, l, s);
00358   
00359   dialog->addDoubleItem(prl, pl, item->text(3).toDouble(), 0, 9999999999.0);
00360   
00361   dialog->addDoubleItem(vl, pl, item->text(2).toDouble(), 1, 99999999);
00362   
00363   int rc = dialog->exec();
00364 
00365   if (rc == QDialog::Accepted)
00366   {
00367     QString symbol;
00368     dialog->getSymbol(sl, symbol);
00369     if (symbol.isNull())
00370       QMessageBox::information(this, tr("Qtstalker: Error"), tr("No symbol selected."));
00371     else
00372     {
00373       QString action;
00374       dialog->getCombo(al, action);
00375       double vol = dialog->getDouble(vl);
00376       double price = dialog->getDouble(prl);
00377 
00378       QFileInfo fi(symbol);
00379       item->setText(0, fi.fileName());
00380       item->setText(1, action);
00381       item->setText(2, QString::number(vol));
00382       item->setText(3, QString::number(price));
00383 
00384       updatePortfolioItems();
00385     }
00386   }
00387 
00388   delete dialog;
00389 }
00390 
00391 void PortfolioDialog::buttonStatus (QListViewItem *i)
00392 {
00393   QString s("edit");
00394   QString s2("delete");
00395   
00396   if (! i)
00397   {
00398     toolbar->setButtonStatus(s, FALSE);
00399     toolbar->setButtonStatus(s2, FALSE);
00400   }
00401   else
00402   {
00403     toolbar->setButtonStatus(s, TRUE);
00404     toolbar->setButtonStatus(s2, TRUE);
00405   }
00406 }
00407 
00408 double PortfolioDialog::futuresProfit (QString &sym, double diff)
00409 {
00410   FuturesData *fd = new FuturesData();
00411   fd->setSymbol(sym);
00412   double rate = fd->getRate();
00413   double t = diff * rate;
00414   delete fd;
00415 
00416   return t;
00417 }
00418 
00419 void PortfolioDialog::itemDoubleClicked (QListViewItem *item, const QPoint &, int)
00420 {
00421   if (! item)
00422     return;
00423     
00424   modifyItem();    
00425 }
00426 
00427 void PortfolioDialog::slotHelp ()
00428 {
00429   QString s = "portfolios.html";
00430   HelpWindow *hw = new HelpWindow(this, s);
00431   hw->show();
00432 }
00433