1 //  This file is part of Qt Bitcoin Trader
2 //      https://github.com/JulyIGHOR/QtBitcoinTrader
3 //  Copyright (C) 2013-2021 July Ighor <julyighor@gmail.com>
4 //
5 //  This program is free software: you can redistribute it and/or modify
6 //  it under the terms of the GNU General Public License as published by
7 //  the Free Software Foundation, either version 3 of the License, or
8 //  (at your option) any later version.
9 //
10 //  In addition, as a special exception, the copyright holders give
11 //  permission to link the code of portions of this program with the
12 //  OpenSSL library under certain conditions as described in each
13 //  individual source file, and distribute linked combinations including
14 //  the two.
15 //
16 //  You must obey the GNU General Public License in all respects for all
17 //  of the code used other than OpenSSL. If you modify file(s) with this
18 //  exception, you may extend this exception to your version of the
19 //  file(s), but you are not obligated to do so. If you do not wish to do
20 //  so, delete this exception statement from your version. If you delete
21 //  this exception statement from all source files in the program, then
22 //  also delete it here.
23 //
24 //  This program is distributed in the hope that it will be useful,
25 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
26 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
27 //  GNU General Public License for more details.
28 //
29 //  You should have received a copy of the GNU General Public License
30 //  along with this program.  If not, see <http://www.gnu.org/licenses/>.
31 
32 #ifndef QTBITCOINTRADER_H
33 #define QTBITCOINTRADER_H
34 
35 #include <QMainWindow>
36 
37 #include "ui_qtbitcointrader.h"
38 #include "depthmodel.h"
39 #include <QCloseEvent>
40 #include <QSortFilterProxyModel>
41 #include <QSystemTrayIcon>
42 #include <QSettings>
43 #include <QMenu>
44 #include <QTime>
45 #include "tradesmodel.h"
46 #include "ordersmodel.h"
47 #include "orderitem.h"
48 #include "historymodel.h"
49 #include <QKeyEvent>
50 #include "currencypairitem.h"
51 #include "script/rulewidget.h"
52 #include "script/scriptwidget.h"
53 #include "feecalculator.h"
54 #include "percentpicker.h"
55 #include <QScrollArea>
56 #include <time.h>
57 #include <QElapsedTimer>
58 #include "debugviewer.h"
59 #include <QTextToSpeech>
60 
61 class Exchange;
62 class QDockWidget;
63 class ConfigManager;
64 class ConfigManagerDialog;
65 class DockHost;
66 class NetworkMenu;
67 class CurrencyMenu;
68 class CurrencySignLoader;
69 class ChartsView;
70 class NewsView;
71 class TraderSpinBox;
72 
73 struct GroupStateItem
74 {
GroupStateItemGroupStateItem75     GroupStateItem(const QString& newName, bool newEnabled):
76         name(newName),
77         enabled(newEnabled)
78     {
79         elapsed.restart();
80     }
81     QString name;
82     bool enabled;
83     QElapsedTimer elapsed;
84 };
85 
86 class QtBitcoinTrader : public QMainWindow
87 {
88     Q_OBJECT
89 
90 public:
91     Ui::QtBitcoinTraderClass ui;
92 
93     void addRuleByHolder(RuleHolder& holder, bool isEnabled, QString titleName);
94 
95     QStringList getRuleGroupsNames();
96     QStringList getScriptGroupsNames();
97     int getOpenOrdersCount(int all = 0);
98     void fixTableViews(QWidget* wid);
99     double getIndicatorValue(const QString&);
100     QMap<QString, QDoubleSpinBox*> indicatorsMap;
101 
102     bool feeCalculatorSingleInstance;
103     FeeCalculator* feeCalculator;
104 
105     double meridianPrice;
106     double availableAmount;
107     int exchangeId;
108     double getAvailableBTC();
109     double getAvailableUSD();
110     double getAvailableUSDtoBTC(double price);
111 
112     double getFeeForUSDDec(double usd);
113 
114     double floatFee;
115     double floatFeeDec;
116     double floatFeeInc;
117 
118     void addPopupDialog(int);
119 
120     void setupClass();
isValidSize(QSize * sizeV)121     bool isValidSize(QSize* sizeV)
122     {
123         if (sizeV->width() < 3 || sizeV->width() > 2000 || sizeV->height() < 3 || sizeV->height() > 2000)
124             return false;
125 
126         return true;
127     }
128     void reloadLanguage(const QString& preferedLangFile = "");
129     void fixAllChildButtonsAndLabels(QWidget* par);
130     void fixDecimals(QWidget* par);
131     void fixAllCurrencyLabels(QWidget* par);
132     void fillAllBtcLabels(QWidget* par, QString curName);
133     void fillAllUsdLabels(QWidget* par, QString curName);
134 
135     QByteArray getMidData(const QString& a, QString b, QByteArray* data);
136     QtBitcoinTrader();
137     ~QtBitcoinTrader();
138 
139     OrdersModel* ordersModel;
140 
141     qint64 currencyChangedDate;
142 
143     QSettings* iniSettings;
144     bool isValidSoftLag;
145     void beep(bool noBlink = false);
146     void playWav(const QString&, bool noBlink = false);
147     void blinkWindow();
148 
149     bool confirmOpenOrder;
150     void apiSellSend(const QString& symbol, double btc, double price);
151     void apiBuySend(const QString& symbol, double btc, double price);
152 
153     QTime lastRuleExecutedTime;
154 
155     bool confirmExitApp();
156     bool hasWorkingRules();
157     bool executeConfirmExitDialog();
158 
159     QSortFilterProxyModel* ordersSortModel;
160     bool currentlyAddingOrders;
161     void keyPressEvent(QKeyEvent* event);
162     void closeEvent(QCloseEvent* event);
163     void changeEvent(QEvent* event);
164 
165     bool isDetachedLog;
166     bool isDetachedTrades;
167     bool isDetachedRules;
168     bool isDetachedDepth;
169     bool isDetachedCharts;
170 
171     void setColumnResizeMode(QTableView*, int, QHeaderView::ResizeMode);
172     void setColumnResizeMode(QTableView*, QHeaderView::ResizeMode);
173 
174     void clearPendingGroup(const QString&);
175 
176     double getVolumeByPrice(const QString& symbol, double price, bool isAsk);
177     double getPriceByVolume(const QString& symbol, double size, bool isAsk);
178 
179     void fixWidthComboBoxGroupByPrice();
180 
181     bool closeToTray;
182 
183     ChartsView* chartsView = nullptr;
184     NewsView* newsView = nullptr;
185 
186     QScopedPointer<QTimer> secondTimer;
187 private:
188     QList<GroupStateItem> pendingGroupStates;
189 
190     void setSpinValue(QDoubleSpinBox* spin, double val);
191     void setSpinValueP(QDoubleSpinBox* spin, double& val);
192     QWidget* windowWidget;
193     QMenu copyTableValuesMenu;
194     QTableView* lastCopyTable;
195 
196     void copyInfoFromTable(QTableView* table, QAbstractItemModel* model, int i);
197 
198     bool swapedDepth;
199     DepthModel* depthAsksModel;
200     DepthModel* depthBidsModel;
201     TradesModel* tradesModel;
202     HistoryModel* historyModel;
203     void fixDepthBidsTable();
204     void clearDepth();
205     void calcOrdersTotalValues();
206     void ruleTotalToBuyValueChanged();
207     void ruleAmountToReceiveValueChanged();
208     void ruleTotalToBuyBSValueChanged();
209     void ruleAmountToReceiveBSValueChanged();
210     bool isDataPending;
211     QElapsedTimer softLagTime;
212     QElapsedTimer depthLagTime;
213     bool waitingDepthLag;
214 
215     QMenu* trayMenu;
216     QString windowTitleP;
217     QSystemTrayIcon* trayIcon;
218     QString profileName;
219     void makeRitchValue(QString* text);
220     bool checkForUpdates;
221 
222     int lastLoadedCurrency;
223 
224     bool constructorFinished;
reject()225     void reject() {}
226     QString clearData(QString data);
227 
228     QString appDir;
229     bool showingMessage;
230 
231     bool balanceNotLoaded;
232     bool marketPricesNotLoaded;
233     void checkValidSellButtons();
234     void checkValidBuyButtons();
235 
236     bool sellLockBtcToSell;
237     bool sellLockPricePerCoin;
238     bool sellLockAmountToReceive;
239 
240     bool buyLockTotalBtc;
241     bool buyLockTotalBtcSelf;
242     bool buyLockPricePerCoin;
243 
244     bool profitSellThanBuyUnlocked;
245     bool profitBuyThanSellUnlocked;
246     bool profitBuyThanSellChangedUnlocked;
247     bool profitSellThanBuyChangedUnlocked;
248 
249     DebugViewer* debugViewer;
250 
251     void translateUnicodeStr(QString* str);
252 
253     void checkIsTabWidgetVisible();
254 
255     void clearTimeOutedTrades();
256     void depthSelectOrder(QModelIndex, bool isSel, int type = 0);
257     double tradesPrecentLast;
258 
259     void repeatOrderFromTrades(int type, int row);
260     void repeatOrderFromValues(int type, double price, double amount, bool availableOnly = true);
261     void repeatSelectedOrderByType(int type, bool availableOnly = true);
262 
263     void updateTrafficTotalValue();
264     void setCurrencyPairsList();
265 
266     qint16 currentPopupDialogs;
267     NetworkMenu* networkMenu;
268     CurrencyMenu* currencyMenu;
269     QScopedPointer<CurrencySignLoader> currencySignLoader;
270 
271     QElapsedTimer historyForceUpdate;
272     QElapsedTimer speedTestTime;
273     QElapsedTimer lastMessageTime;
274 
275 public slots:
276     void sendIndicatorEvent(const QString& symbol, const QString& name, double value);
277 
278     void setRuleTabRunning(const QString&, bool);
279     void startApplication(const QString&, QStringList);
280     void setGroupRunning(const QString& name, bool enabled);
281     void setGroupState(const QString& name, bool enabled);
282     bool getIsGroupRunning(const QString& name);
283 
284     void reloadScripts();
285     void on_buyPercentage_clicked();
286     void on_sellPercentage_clicked();
287     void on_buyPriceAsMarketBid_clicked();
288     void on_sellPriceAsMarketAsk_clicked();
289     void trafficTotalToZero_clicked();
290     void on_buttonNight_clicked();
291     void ordersFilterChanged();
292     void cancelOrderByXButton();
293     void cancelPairOrders(const QString&);
294     void cancelAskOrders(const QString&);
295     void cancelBidOrders(const QString&);
296 
297     void repeatBuySellOrder();
298     void repeatBuyOrder();
299     void repeatSellOrder();
300     void copySelectedRow();
301     void copyDate();
302     void copyAmount();
303     void copyPrice();
304     void copyTotal();
305 
306     void tableCopyContextMenuRequested(QPoint);
307 
308     void on_rulesTabs_tabCloseRequested(int);
309     void on_buttonAddRuleGroup_clicked();
310 
311     void availableAmountChanged(const QString&, double);
312     void precentBidsChanged(double);
313     void depthRequested();
314     void depthRequestReceived();
315     void on_swapDepth_clicked();
316     void checkValidOrdersButtons();
317     void cancelOrder(const QString&, const QByteArray&);
318     void volumeAmountChanged(double, double);
319     void setLastTrades10MinVolume(double);
320     void on_depthAutoResize_toggled(bool);
321     void on_depthComboBoxLimitRows_currentIndexChanged(int);
322     void on_comboBoxGroupByPrice_currentIndexChanged(int);
323     void depthSelectSellOrder(QModelIndex);
324     void depthSelectBuyOrder(QModelIndex);
325     void historyDoubleClicked(QModelIndex);
326     void tradesDoubleClicked(QModelIndex);
327     void setDataPending(bool);
328     void anyDataReceived();
329     void depthFirstOrder(const QString&, double, double, bool);
330     void depthSubmitOrders(const QString&, QList<DepthItem>*, QList<DepthItem>*);
331     void showErrorMessage(const QString&);
332     void saveAppState();
333     void on_widgetStaysOnTop_toggled(bool);
334     void setSoftLagValue(int);
335     void trayActivated(QSystemTrayIcon::ActivationReason);
336     void buttonMinimizeToTray();
337 
338     void secondSlot();
339     void setTradesScrollBarValue(int);
340     void tabTradesIndexChanged(int);
341     void tabTradesScrollUp();
342     void addLastTrades(const QString& symbol, QList<TradesItem>* newItems);
343 
344     void sayText(const QString&);
345 
346     void loginChanged(const QString&);
347 
348     void orderBookChanged(const QString&, QList<OrderItem>* orders);
349 
350     void setApiDown(bool);
351 
352     void identificationRequired(QString);
353 
354     void updateLogTable();
355     void historyChanged(QList<HistoryItem>*);
356 
357     void accLastSellChanged(const QString&, double);
358     void accLastBuyChanged(const QString&, double);
359 
360     void orderCanceled(const QString&, QByteArray);
361     void ordersIsAvailable();
362     void ordersIsEmpty();
363 
364     void languageChanged();
365     void on_zeroSellThanBuyProfit_clicked();
366     void on_zeroBuyThanSellProfit_clicked();
367     void profitSellThanBuy();
368     void profitSellThanBuyCalc();
369     void profitBuyThanSellCalc();
370     void profitBuyThanSell();
371 
372     void buttonNewWindow();
373 
374     void currencyMenuChanged(int);
375 
376     void on_calcButton_clicked();
377     void checkUpdate();
378 
379     void accFeeChanged(const QString&, double);
380     void accBtcBalanceChanged(const QString&, double);
381     void accUsdBalanceChanged(const QString&, double);
382 
383     void indicatorHighChanged(const QString&, double);
384     void indicatorLowChanged(const QString&, double);
385     void indicatorSellChanged(const QString&, double);
386     void indicatorLastChanged(const QString&, double);
387     void indicatorBuyChanged(const QString&, double);
388     void indicatorVolumeChanged(const QString&, double);
389 
390 
391     void on_accountUSD_valueChanged(double);
392     void on_accountBTC_valueChanged(double);
393     void on_marketBid_valueChanged(double);
394     void on_marketAsk_valueChanged(double);
395     void on_marketLast_valueChanged(double);
396 
397     void balanceChanged(double);
398 
399     void on_ordersCancelBidsButton_clicked();
400     void on_ordersCancelAsksButton_clicked();
401     void on_ordersCancelSelected_clicked();
402     void on_ordersCancelAllButton_clicked();
403     void cancelAllCurrentPairOrders();
404     void on_accountFee_valueChanged(double);
405 
406     void on_buyTotalBtcAllIn_clicked();
407     void on_buyTotalBtcHalfIn_clicked();
408     void on_buyPriceAsMarketAsk_clicked();
409     void on_buyPriceAsMarketLastPrice_clicked();
410     void buyBitcoinsButton();
411 
412     void sellBitcoinButton();
413     void on_sellPriceAsMarketBid_clicked();
414     void on_sellPricePerCoinAsMarketLastPrice_clicked();
415     void on_sellTotalBtcAllIn_clicked();
416     void on_sellTotalBtcHalfIn_clicked();
417 signals:
418     void indicatorEventSignal(const QString& symbol, const QString& name, double value);
419     void themeChanged();
420     void reloadDepth();
421     void cancelOrderByOid(const QString&, const QByteArray&);
422     void apiSell(const QString& symbol, double btc, double price);
423     void apiBuy(const QString& symbol, double btc, double price);
424     void getHistory(bool);
425     void clearValues();
426     void clearCharts();
427     void addBound(double, bool);
428 private slots:
429     void uninstall();
430     void on_buttonAddScript_clicked();
431     void on_helpButton_clicked();
432     void depthVisibilityChanged(bool);
433 
434 private:
435     QScopedPointer<QTextToSpeech> ttsEngine;
436     void initDocks();
437     void createActions();
438     void createMenu();
439     QDockWidget* createDock(QWidget* widget, const QString& title);
440     void moveWidgetsToDocks();
441     void translateTab(QWidget* tab);
442     void lockLogo(bool lock);
443     void initConfigMenu();
444     void setupWidgets();
445 
446     QScopedPointer<QThread> currentExchangeThread;
447 
448 private slots:
449     void onActionSendBugReport();
450     void onActionAbout();
451     void onActionAboutQt();
452     void onActionLockDocks(bool checked);
453     void onActionConfigManager();
454     void onActionSettings();
455     void onActionDebug();
456     void onMenuConfigTriggered();
457     void onConfigChanged();
458     void onConfigError(const QString& error);
459     void exitApp();
460 
461 private:
462     bool         lockedDocks;
463     QAction*     actionExit;
464     QAction*     actionUpdate;
465     QAction*     actionSendBugReport;
466     QAction*     actionAbout;
467     QAction*     actionAboutQt;
468     QAction*     actionLockDocks;
469     QAction*     actionConfigManager;
470     QAction*     actionSettings;
471     QAction*     actionDebug;
472     QAction*     actionUninstall;
473     QMenu*       menuFile;
474     QMenu*       menuView;
475     QMenu*       menuConfig;
476     QMenu*       menuHelp;
477     ConfigManagerDialog*    configDialog;
478     DockHost*    dockHost;
479     QDockWidget* dockLogo;
480     QDockWidget* dockDepth;
481 
482 public:
483     TraderSpinBox* buyTotalSpend;
484     TraderSpinBox* buyPricePerCoin;
485     TraderSpinBox* buyTotalBtc;
486     TraderSpinBox* profitLossSpinBox;
487     TraderSpinBox* profitLossSpinBoxPrec;
488     TraderSpinBox* sellTotalBtc;
489     TraderSpinBox* sellPricePerCoin;
490     TraderSpinBox* sellAmountToReceive;
491     TraderSpinBox* sellThanBuySpinBox;
492     TraderSpinBox* sellThanBuySpinBoxPrec;
493 
494 private slots:
495     void buyTotalSpend_valueChanged(double);
496     void buyPricePerCoin_valueChanged(double);
497     void buyTotalBtc_valueChanged(double);
498     void profitLossSpinBox_valueChanged(double);
499     void profitLossSpinBoxPrec_valueChanged(double);
500     void sellTotalBtc_valueChanged(double);
501     void sellPricePerCoin_valueChanged(double);
502     void sellAmountToReceive_valueChanged(double);
503     void sellThanBuySpinBox_valueChanged(double);
504     void sellThanBuySpinBoxPrec_valueChanged(double);
505 };
506 
507 #endif // QTBITCOINTRADER_H
508