void BalanceWindow::on_settingsAction_triggered() { SettingsDialog *d = new SettingsDialog(settings, this); connect(d,SIGNAL(testEmail()), this, SLOT(sendEmail())); d->setModal(true); d->show(); }
/** * Sends an alert email detailing that all the given ips have been blocked. */ void sendSyncSummaryEmail(char **ips, int numIPs) { char *body; int length; char *subject; int bodySize; int i; DBG("Sending summary email\n"); length = (numIPs * 16 + 512); body = malloc(sizeof(char *) * length); subject = "Blocked ips from brutelock server"; snprintf(body, length, "The following ips have been marked by the brutelock server and are being blocked:\n"); for (i = 0; i < numIPs; i++) { strncat(body, ips[i], length); strncat(body, "\n", length); } sendEmail(subject, body); free(body); }
bool CMailManager::SendMail(const char* pTitle, const char* pText) { //·¢ËÍÓʼþ if(NULL == m_pMailAlert || 0 == m_pMailAlert->m_u4MailID) { OUR_DEBUG((LM_ERROR, "[CMailManager::SendMail]MailID not set.\n")); return false; } unsigned char * pMail = NULL; pMail = (unsigned char * )ACE_OS::calloc(1, 1); int nRet = 0; nRet = mailText(&pMail, (const unsigned char *)m_pMailAlert->m_szFromMailAddr, (const unsigned char *)m_pMailAlert->m_szToMailAddr, (const unsigned char *)pTitle, (const unsigned char *)pText); nRet = mailEnd(&pMail); ACE_HANDLE fd; nRet = connectSmtp(fd, (const unsigned char *)m_pMailAlert->m_szMailUrl, m_pMailAlert->m_u4MailPort); if(nRet != 0) { OUR_DEBUG((LM_ERROR, "[CMailManager::SendMail]MailID connectSmtp error.\n")); free(pMail); return false; } nRet = authEmail(fd, (const unsigned char *)m_pMailAlert->m_szFromMailAddr, (const unsigned char *)m_pMailAlert->m_szMailPass); if(nRet != 0) { OUR_DEBUG((LM_ERROR, "[CLogFile::SendMail]MailID authEmail error.\n")); free(pMail); return false; } nRet = sendEmail(fd, (const unsigned char *)m_pMailAlert->m_szFromMailAddr, (const unsigned char *)m_pMailAlert->m_szToMailAddr, (const unsigned char *)pMail, (const int)strlen((const char *)pMail)); if(nRet != 0) { OUR_DEBUG((LM_ERROR, "[CLogFile::SendMail]MailID sendEmail error.\n")); free(pMail); return false; } free(pMail); return true; }
void SBookWidget::CreateMenuBar(QLayout *topLayout) { QMenuBar *menubar = new QMenuBar( this ); menubar->setSeparator( QMenuBar::InWindowsStyle ); QPopupMenu *file = new QPopupMenu; file->insertItem( "&New File", this, SLOT(menuFileNew()) ); file->insertItem( "&Open", this, SLOT(menuFileOpen()),CTRL+Key_O ); file->insertSeparator(); file->insertItem( "&Save", this, SLOT(menuSave()),CTRL+Key_S ); file->insertItem( "Save &As ...", this, SLOT(menuSaveAs())); file->insertItem( "E&xport ...", this, SLOT(menuExport())); file->insertItem( "I&mport ...", this, SLOT(menuImport())); file->insertSeparator(); file->insertItem( "&Print ...", this, SLOT(menuFilePrint()), CTRL+Key_P); file->insertItem( "&Setup Label Printer ...", this, SLOT(menuFileSetupLabelPrinter())); file->insertSeparator(); file->insertItem( "&Inspector", this, SLOT(menuShowInspector()),CTRL+SHIFT+Key_I); file->insertItem( "&Exit", this, SLOT(menuFileExit()) ); menubar->insertItem( "&File", file ); /*************/ /* ENTRY */ /*************/ QPopupMenu *entry = new QPopupMenu; entry->insertItem( "&New Entry", this, SLOT(menuEntryNew()),CTRL+Key_N ); entry->insertItem( "&Delete Entry", this, SLOT(menuEntryDelete()),CTRL+Key_D ); entry->insertItem( "&Find Entry", this, SLOT(menuFind()), CTRL+Key_F ); entry->insertSeparator(); entry->insertItem( "&Send Email", this, SLOT(sendEmail()), CTRL+Key_E ); entry->insertItem( "Print &Label ...", this, SLOT(menuFilePrintLabel()), CTRL+Key_L); entry->insertItem( "Print Label 2 ...", this, SLOT(menuFilePrintLabel2()), CTRL+SHIFT+Key_L); menubar->insertItem( "&Entry", entry); /****************************************************************/ QPopupMenu *help = new QPopupMenu; help->insertItem( "&About " APP_NAME " " APP_VERSION, this, SLOT(menuAbout()) ); help->insertSeparator(); help->insertItem( "About &Qt" , this, SLOT(menuAboutQt()) ); menubar->insertItem( "&Help",help); // ...and tell the layout about it. topLayout->setMenuBar( menubar ); }
Donations::Donations(QWidget *parent) : QWidget(parent) { setupUi(this); connect(dateFrom, SIGNAL(dateChanged(QDate)), this, SLOT(searchData())); connect(dateUntil, SIGNAL(dateChanged(QDate)), this, SLOT(searchData())); connect(btnExport, SIGNAL(clicked()), this, SLOT(exportData())); connect(btnEmail, SIGNAL(clicked()), this, SLOT(sendEmail())); connect(sectionList, SIGNAL(currentIndexChanged(int)), this, SLOT(selectSection())); connect(yearList, SIGNAL(itemSelectionChanged()), this, SLOT(selectYear())); tableModel = new QSqlQueryModel(tableView); donationsModel = new QSqlQueryModel(donationsTable); fileImport = false; loadData(); loadSectionDonations(); }
/** * Send an email alerting that the given host has been blocked. */ void sendAlertEmail(char *ip) { char body[2048]; char subject[512]; int i; DBG("Sending alert email\n"); // Make darn sure we got an IP so that we don't pass through a crazy // domain name and get ourselves hacked for (i = 0; i < strnlen(ip, 256); i++ ) { if (!isdigit(ip[i]) && ip[i] != '.') errx(1, "Didn't get an ip where one expected in sendAlertEmail"); } snprintf(subject, 512, "Blocked %s", ip); snprintf(body, 2048, "The following ip has been blocked by brutelock: %s", ip); sendEmail(subject, body); }
void BalanceWindow::updateInfo() { double balance = settings->balance(); ui->balance->setText(QString("%1").arg(balance)); updateTrayIcon(balance); ui->lastUpdate->setText(settings->lastUpdate()); ui->dayTo->setText(QString("%1").arg(settings->dayToPay())); ui->payTo->setText(settings->needPay()); if(settings->levelBalance()){ if(settings->trayNotice()) showMessage(settings->levelBalance()); if(settings->emailNotice()) sendEmail(settings->levelBalance()); } setStatus("Готово"); }
int main() { int fd = 0, ret; unsigned char *mail = NULL; const unsigned char *filePath = "./test.jpg"; const unsigned char *mailSubject = "for my love."; const unsigned char *mailBody = "I love you alice!!"; const unsigned char *fromMailAddr= "*****@*****.**"; const unsigned char *mailPasswd= "ecila"; const unsigned char *toMailAddr= "*****@*****.**"; const unsigned char *smtpUrl = "smtp.163.com"; mail = calloc(1, 1); /* prepare mail data */ ret = mailText(&mail, fromMailAddr, toMailAddr, mailSubject, mailBody); ret = mailAttachment(&mail, filePath); ret = mailEnd(&mail); SMTP_Print6("\r\n%s \r\n", mail); printf("\r\nprepare email OK ...\r\n"); /* send to buddy */ fd = connectSmtp(smtpUrl, SMTP_PORT); printf("connect OK ...\r\n"); ret = authEmail(fd, fromMailAddr, mailPasswd); printf("auth OK ...\r\n"); ret = sendEmail(fd, fromMailAddr, toMailAddr, mail, strlen(mail)); printf("send OK ...\r\n"); return 0; }
// Loads the file, sends the email, and logs the results. // Sets the m_running flag to false when done. void SmtpThread::runThread(void) { int tryCount = 0; CkString lastErrorText; tryAgain: if (!m_logErrorsOnly) { if (tryCount > 0) { logNameValue("Re-trying",m_filename); logNameValueInt("TryCount",tryCount + 1); } else { logNameValue("Sending",m_filename); } } bool success = false; bool bFailureIsFinal = true; success = sendEmail(bFailureIsFinal); m_mailman->get_LastErrorText(lastErrorText); if (success) { if (m_saveSent) { moveToSentDir(); } else { CkString strEmlPath; fullFilePath(m_queueDir.c_str(),m_filename.c_str(),strEmlPath); #if defined(TEST_SMTPQ) logNameValue("deletingFile3",strEmlPath.getString()); #endif BOOL b = DeleteFile(strEmlPath.getString()); if (!b) { CkString strWindowsError; strWindowsError.appendLastWindowsError(); logNameValue("Failed to delete file",m_filename); logNameValue("WindowsError",strWindowsError.getString()); // This EML was abandoned in the queue directory.. m_emlAbandoned = true; } } if (!m_logErrorsOnly) { logNameValue("Send successful",m_filename); } } else if (bFailureIsFinal || (!m_maxRetryCount) || (tryCount > m_maxRetryCount)) { if (bFailureIsFinal) { logNameValue("Send Failed, error is final and a retry won't succeed.",m_filename); } else { logNameValue("Send Failed, no more retries",m_filename); } CkString strEmlPath; fullFilePath(m_queueDir.c_str(),m_filename.c_str(),strEmlPath); CkString strToPath; fullFilePath(m_undeliverableDir.c_str(),m_filename.c_str(),strToPath); #if defined(TEST_SMTPQ) logNameValue("movingFile2",strEmlPath.getString()); logNameValue("movingTo2",strToPath.getString()); #endif if (!MoveFile(strEmlPath.getString(),strToPath.getString())) //if (!MoveFile(strEmlPath.getString(),m_undeliverableDir.c_str())) { #if defined(TEST_SMTPQ) logNameValue("deletingFile2",strEmlPath.getString()); #endif if (!DeleteFile(strEmlPath.getString())) { // This EML was abandoned in the queue directory.. m_emlAbandoned = true; } } } else { logString(lastErrorText.getString()); logNameValue("Send Failed, will try again",m_filename); tryCount++; int delayMs = 1000; /* tryCount delayTime -------- --------- 1 5 sec 2 10 sec 3 15 sec 4 1 min 5 1.5 minutes 6 2 minutes 7 5 minutes 8 10 minutes 9 15 minutes 10 20 minutes */ if (tryCount < 4) { // 5 seconds * tryCount delayMs = 5000 * tryCount; } else if (tryCount < 7) { delayMs = 30000 * (tryCount-2); } else // up to g_maxRetryCount (max 10) tries { delayMs = 300000 * (tryCount-6); } logNameValueInt("tryCount",tryCount); logNameValueInt("sleepMillisec",delayMs); // When waiting for the retry, continue updating the heartbeat so that the ThreadManager // knows the thread is not dead. while (delayMs) { int t = delayMs > 1000 ? 1000 : delayMs; ::Sleep(t); delayMs -= t; } goto tryAgain; } m_running = false; return; }
///Constructor HistoryTreeItem::HistoryTreeItem(QWidget *parent ,QString phone) : QWidget(parent), m_pItemCall(0),m_pMenu(0),m_pAudioSlider(0),m_pTimeLeftL(0),m_pTimePlayedL(0),m_pPlayer(0),m_pContact(0) { setContextMenuPolicy(Qt::CustomContextMenu); m_pCallAgain = new KAction(this); m_pAddContact = new KAction(this); m_pCopy = new KAction(this); m_pEmail = new KAction(this); m_pAddToContact = new KAction(this); m_pBookmark = new KAction(this); m_pCallAgain->setShortcut ( Qt::Key_Enter ); m_pCallAgain->setText ( i18n("Call Again") ); m_pCallAgain->setIcon ( KIcon(ICON_DIALING) ); m_pAddToContact->setShortcut ( Qt::CTRL + Qt::Key_E ); m_pAddToContact->setText ( i18n("Add Number to Contact") ); m_pAddToContact->setIcon ( KIcon("list-resource-add") ); m_pAddToContact->setDisabled ( true ); m_pAddContact->setShortcut ( Qt::CTRL + Qt::Key_E ); m_pAddContact->setText ( i18n("Add Contact") ); m_pAddContact->setIcon ( KIcon("contact-new") ); m_pCopy->setShortcut ( Qt::CTRL + Qt::Key_C ); m_pCopy->setText ( i18n("Copy") ); m_pCopy->setIcon ( KIcon("edit-copy") ); m_pCopy->setDisabled ( true ); m_pEmail->setShortcut ( Qt::CTRL + Qt::Key_M ); m_pEmail->setText ( i18n("Send Email") ); m_pEmail->setIcon ( KIcon("mail-message-new") ); m_pEmail->setDisabled ( true ); m_pBookmark->setShortcut ( Qt::CTRL + Qt::Key_D ); m_pBookmark->setText ( i18n("Bookmark") ); m_pBookmark->setIcon ( KIcon("bookmarks") ); m_pPlay = new QToolButton(this); m_pPlay->setIcon(KIcon("media-playback-start")); m_pPlay->setMinimumSize(30,30); m_pPlay->setMaximumSize(30,30); m_pPlay->setSizePolicy(QSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed)); m_pPlay->setVisible(false); m_pRemove = new QToolButton(this); m_pRemove->setIcon(KIcon("list-remove")); m_pRemove->setMinimumSize(30,30); m_pRemove->setMaximumSize(30,30); m_pRemove->setSizePolicy(QSizePolicy(QSizePolicy::Fixed,QSizePolicy::Fixed)); m_pRemove->setVisible(false); connect(m_pCallAgain , SIGNAL(triggered()) , this , SLOT(callAgain() )); connect(m_pAddContact , SIGNAL(triggered()) , this , SLOT(addContact() )); connect(m_pCopy , SIGNAL(triggered()) , this , SLOT(copy() )); connect(m_pEmail , SIGNAL(triggered()) , this , SLOT(sendEmail() )); connect(m_pAddToContact , SIGNAL(triggered()) , this , SLOT(addToContact() )); connect(m_pBookmark , SIGNAL(triggered()) , this , SLOT(bookmark() )); connect(m_pPlay , SIGNAL(clicked() ) , this , SLOT(showRecordPlayer() )); connect(m_pRemove , SIGNAL(clicked() ) , this , SLOT(removeRecording() )); connect(this , SIGNAL(customContextMenuRequested(QPoint)) , this , SLOT(showContext(QPoint) )); m_pIconL = new QLabel( this ); m_pPeerNameL = new QLabel( this ); m_pCallNumberL = new QLabel( this ); m_pLengthL = new QLabel( this ); m_pTimeL = new QLabel( this ); m_pIconL->setMinimumSize(70,0); m_pIconL->setSizePolicy(QSizePolicy::Fixed,QSizePolicy::MinimumExpanding); QSpacerItem* verticalSpacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Expanding); m_pMainLayout = new QGridLayout(this); m_pMainLayout->addWidget ( m_pIconL , 0 , 0 , 4 , 1 ); m_pMainLayout->addWidget ( m_pPeerNameL , 0 , 1 ); m_pMainLayout->addWidget ( m_pCallNumberL , 1 , 1 ); m_pMainLayout->addWidget ( m_pTimeL , 2 , 1 ); m_pMainLayout->addItem ( verticalSpacer , 4 , 1 ); m_pMainLayout->addWidget ( m_pPlay , 0 , 2 , 4 , 1 ); m_pMainLayout->addWidget ( m_pRemove , 0 , 3 , 4 , 1 ); m_pMainLayout->addWidget ( m_pLengthL , 0 , 4 , 4 , 1 ); setLayout(m_pMainLayout); setMinimumSize(QSize(50, 30)); setMaximumSize(QSize(300,99999)); setSizePolicy(QSizePolicy(QSizePolicy::Minimum,QSizePolicy::Minimum)); if (!phone.isEmpty()) { getContactInfo(phone); m_pCallNumberL->setText(phone); m_PhoneNumber = phone; } }
void detectorEmail::doAction() { sendEmail(emailTo, emailServer, emailMessage); }
/** * Alarm task that handles sounding the alarm and sending * out the alerts */ void alarmTask(void *data) { // Error reference INT8U err; // Result variables char *result; auto char realResult; // Loop forever while(1) { //Read MSG Queue, wait forever for message result = (char *)OSQPend(msgQueuePtr, 0, &err); realResult = *result; // Debug printf("Alarm Task Run\n"); // Check for zone 1 if(realResult == '0') { printf("\nZone 1 Tripped!!!!\n"); digOut(ID_BUZZER, ON); digOut(LED_0_ID, ON); // Update the current alarm state OSSemPend(alarmSem, 0, &err); zone0Alarm = ON; alarming = ON; OSSemPost(alarmSem); // Send the alert sendEmail(0); } else if(realResult == '1') { printf("\nZone 12Tripped!!!!\n"); digOut(ID_BUZZER, ON); digOut(LED_1_ID, ON); // Update the current alarm state OSSemPend(alarmSem, 0, &err); zone1Alarm = ON; alarming = ON; OSSemPost(alarmSem); // Send the alert sendEmail(1); } else if(realResult == '2') { printf("\nZone 3 Tripped!!!!\n"); digOut(ID_BUZZER, ON); digOut(LED_2_ID, ON); // Update the current alarm state OSSemPend(alarmSem, 0, &err); zone2Alarm = ON; alarming = ON; OSSemPost(alarmSem); // Send the alert sendEmail(2); } else if(realResult == '3') { printf("\nZone 4 Tripped!!!!\n"); digOut(ID_BUZZER, ON); digOut(LED_3_ID, ON); // Update the current alarm state OSSemPend(alarmSem, 0, &err); zone3Alarm = ON; alarming = ON; OSSemPost(alarmSem); // Send the alert sendEmail(3); } } }
void TDEAboutContributor::emailClickedSlot( const TQString &e ) { emit sendEmail( mText[0]->text(), e ) ; }
int main(int argc, char **argv) { // header information std::cout << "Blackbird Bitcoin Arbitrage\nVersion 0.0.2" << std::endl; std::cout << "DISCLAIMER: USE THE SOFTWARE AT YOUR OWN RISK.\n" << std::endl; // read the config file (config.json) json_error_t error; json_t *root = json_load_file("config.json", 0, &error); if (!root) { std::cout << "ERROR: config.json incorrect (" << error.text << ")\n" << std::endl; return 1; } // get config variables int gapSec = json_integer_value(json_object_get(root, "GapSec")); unsigned debugMaxIteration = json_integer_value(json_object_get(root, "DebugMaxIteration")); bool useFullCash = json_boolean_value(json_object_get(root, "UseFullCash")); double untouchedCash = json_real_value(json_object_get(root, "UntouchedCash")); double cashForTesting = json_real_value(json_object_get(root, "CashForTesting")); if (!useFullCash && cashForTesting < 15.0) { std::cout << "ERROR: Minimum test cash is $15.00.\n" << std::endl; return 1; } // function arrays getQuoteType getQuote[] = {Bitfinex::getQuote, OkCoin::getQuote, Bitstamp::getQuote, Kraken::getQuote}; getAvailType getAvail[] = {Bitfinex::getAvail, OkCoin::getAvail, Bitstamp::getAvail, Kraken::getAvail}; sendOrderType sendOrder[] = {Bitfinex::sendOrder, OkCoin::sendOrder, Bitstamp::sendOrder}; isOrderCompleteType isOrderComplete[] = {Bitfinex::isOrderComplete, OkCoin::isOrderComplete, Bitstamp::isOrderComplete}; getActivePosType getActivePos[] = {Bitfinex::getActivePos, OkCoin::getActivePos, Bitstamp::getActivePos, Kraken::getActivePos}; getLimitPriceType getLimitPrice[] = {Bitfinex::getLimitPrice, OkCoin::getLimitPrice, Bitstamp::getLimitPrice, Kraken::getLimitPrice}; // thousand separator std::locale mylocale(""); std::cout.imbue(mylocale); // print precision of two digits std::cout.precision(2); std::cout << std::fixed; // create a parameters structure Parameters params(root); params.addExchange("Bitfinex", 0.0020, true); params.addExchange("OKCoin", 0.0020, false); params.addExchange("Bitstamp", 0.0025, false); params.addExchange("Kraken", 0.0025, true); // CSV file std::string csvFileName; csvFileName = "result_" + printDateTimeFileName() + ".csv"; std::ofstream csvFile; csvFile.open(csvFileName.c_str(), std::ofstream::trunc); // CSV header csvFile << "TRADE_ID,EXCHANGE_LONG,EXHANGE_SHORT,ENTRY_TIME,EXIT_TIME,DURATION,TOTAL_EXPOSURE,BALANCE_BEFORE,BALANCE_AFTER,RETURN\n"; csvFile.flush(); // time structure time_t rawtime; rawtime = time(NULL); struct tm * timeinfo; timeinfo = localtime(&rawtime); bool inMarket = false; int resultId = 0; Result res; res.clear(); // Vector of Bitcoin std::vector<Bitcoin*> btcVec; // create Bitcoin objects for (unsigned i = 0; i < params.nbExch(); ++i) { btcVec.push_back(new Bitcoin(i, params.exchName[i], params.fees[i], params.hasShort[i])); } // cURL CURL* curl; curl_global_init(CURL_GLOBAL_ALL); curl = curl_easy_init(); std::cout << "[ Targets ]" << std::endl; std::cout << " Spread to enter: " << params.spreadEntry * 100.0 << "%" << std::endl; std::cout << " Spread to exit: " << params.spreadExit * 100.0 << "%" << std::endl; std::cout << std::endl; // store current balances std::cout << "[ Current balances ]" << std::endl; std::vector<double> balanceUsd; std::vector<double> balanceBtc; for (unsigned i = 0; i < params.nbExch(); ++i) { balanceUsd.push_back(getAvail[i](curl, params, "usd")); balanceBtc.push_back(getAvail[i](curl, params, "btc")); } // vectors that contains balances after a completed trade std::vector<double> newBalUsd(params.nbExch(), 0.0); std::vector<double> newBalBtc(params.nbExch(), 0.0); for (unsigned i = 0; i < params.nbExch(); ++i) { std::cout << " " << params.exchName[i] << ":\t"; std::cout << balanceUsd[i] << " USD\t" << std::setprecision(6) << balanceBtc[i] << std::setprecision(2) << " BTC" << std::endl; } std::cout << std::endl; std::cout << "[ Cash exposure ]" << std::endl; if (useFullCash) { std::cout << " FULL cash used!" << std::endl; } else { std::cout << " TEST cash used\n Value: $" << cashForTesting << std::endl; } std::cout << std::endl; // wait the next gapSec seconds before starting time(&rawtime); timeinfo = localtime(&rawtime); while ((int)timeinfo->tm_sec % gapSec != 0) { sleep(0.01); time(&rawtime); timeinfo = localtime(&rawtime); } // main loop if (!params.verbose) { std::cout << "Running..." << std::endl; } unsigned currIteration = 0; bool stillRunning = true; while (stillRunning) { time_t currTime = mktime(timeinfo); time(&rawtime); // check if we are already too late if (difftime(rawtime, currTime) > 0) { std::cout << "WARNING: " << difftime(rawtime, currTime) << " second(s) too late at " << printDateTime(currTime) << std::endl; unsigned skip = (unsigned)ceil(difftime(rawtime, currTime) / gapSec); for (unsigned i = 0; i < skip; ++i) { // std::cout << " Skipped iteration " << printDateTime(currTime) << std::endl; for (unsigned e = 0; e < params.nbExch(); ++e) { btcVec[e]->addData(currTime, btcVec[e]->getLastBid(), btcVec[e]->getLastAsk(), 0.0); } // go to next iteration timeinfo->tm_sec = timeinfo->tm_sec + gapSec; currTime = mktime(timeinfo); } std::cout << std::endl; } // wait for the next iteration while (difftime(rawtime, currTime) != 0) { sleep(0.01); time(&rawtime); } if (params.verbose) { if (!inMarket) { std::cout << "[ " << printDateTime(currTime) << " ]" << std::endl; } else { std::cout << "[ " << printDateTime(currTime) << " IN MARKET: Long " << res.exchNameLong << " / Short " << res.exchNameShort << " ]" << std::endl; } } // download the exchanges prices for (unsigned e = 0; e < params.nbExch(); ++e) { double bid = getQuote[e](curl, true); double ask = getQuote[e](curl, false); // add previous price if bid or ask is 0.0 if (bid == 0.0) { bid = btcVec[e]->getLastBid(); std::cout << " WARNING: " << params.exchName[e] << " bid is null, use previous one" << std::endl; } if (ask == 0.0) { ask = btcVec[e]->getLastAsk(); std::cout << " WARNING: " << params.exchName[e] << " ask is null, use previous one" << std::endl; } if (params.verbose) { std::cout << " " << params.exchName[e] << ": \t" << bid << " / " << ask << std::endl; } btcVec[e]->addData(currTime, bid, ask, 0.0); curl_easy_reset(curl); } // load data terminated if (params.verbose) { std::cout << " ----------------------------" << std::endl; } // compute entry point if (!inMarket) { for (unsigned i = 0; i < params.nbExch(); ++i) { for (unsigned j = 0; j < params.nbExch(); ++j) { if (i != j) { if (checkEntry(btcVec[i], btcVec[j], res, params)) { // entry opportunity found // compute exposure res.exposure = std::min(balanceUsd[res.idExchLong], balanceUsd[res.idExchShort]); if (res.exposure == 0.0) { std::cout << " WARNING: Opportunity found but no cash available. Trade canceled." << std::endl; break; } if (useFullCash == false && res.exposure <= cashForTesting) { std::cout << " WARNING: Opportunity found but no enough cash. Need more than TEST cash (min. $" << cashForTesting << "). Trade canceled." << std::endl; break; } if (useFullCash) { // leave untouchedCash res.exposure -= untouchedCash * res.exposure; } else { // use test money res.exposure = cashForTesting; } // check volumes double volumeLong = res.exposure / btcVec[res.idExchLong]->getLastAsk(); double volumeShort = res.exposure / btcVec[res.idExchShort]->getLastBid(); double limPriceLong = getLimitPrice[res.idExchLong](curl, volumeLong, false); double limPriceShort = getLimitPrice[res.idExchShort](curl, volumeShort, true); if (limPriceLong - res.priceLongIn > 0.30 || res.priceShortIn - limPriceShort > 0.30) { std::cout << " WARNING: Opportunity found but not enough volume. Trade canceled." << std::endl; break; } inMarket = true; resultId++; // update result res.id = resultId; res.entryTime = currTime; res.printEntry(); res.maxSpread[res.idExchLong][res.idExchShort] = -1.0; res.minSpread[res.idExchLong][res.idExchShort] = 1.0; int longOrderId = 0; int shortOrderId = 0; // send Long order longOrderId = sendOrder[res.idExchLong](curl, params, "buy", volumeLong, btcVec[res.idExchLong]->getLastAsk()); // send Short order shortOrderId = sendOrder[res.idExchShort](curl, params, "sell", volumeShort, btcVec[res.idExchShort]->getLastBid()); // wait for the orders to be filled sleep(3.0); std::cout << "Waiting for the two orders to be filled..." << std::endl; while (!isOrderComplete[res.idExchLong](curl, params, longOrderId) || !isOrderComplete[res.idExchShort](curl, params, shortOrderId)) { sleep(3.0); } std::cout << "Done" << std::endl; longOrderId = 0; shortOrderId = 0; break; } } } if (inMarket) { break; } } if (params.verbose) { std::cout << std::endl; } } // in market, looking to exit else if (inMarket) { if (checkExit(btcVec[res.idExchLong], btcVec[res.idExchShort], res, params, currTime)) { // exit opportunity found // check current exposure std::vector<double> btcUsed; for (unsigned i = 0; i < params.nbExch(); ++i) { btcUsed.push_back(getActivePos[i](curl, params)); } // check volumes double volumeLong = btcUsed[res.idExchLong]; double volumeShort = btcUsed[res.idExchShort]; double limPriceLong = getLimitPrice[res.idExchLong](curl, volumeLong, true); double limPriceShort = getLimitPrice[res.idExchShort](curl, volumeShort, false); if (res.priceLongOut - limPriceLong > 0.30 || limPriceShort - res.priceShortOut > 0.30) { std::cout << " WARNING: Opportunity found but not enough volume. Trade canceled." << std::endl; } else { res.exitTime = currTime; res.printExit(); // send orders int longOrderId = 0; int shortOrderId = 0; std::cout << std::setprecision(6) << "BTC exposure on " << params.exchName[res.idExchLong] << ": " << volumeLong << std::setprecision(2) << std::endl; std::cout << std::setprecision(6) << "BTC exposure on " << params.exchName[res.idExchShort] << ": " << volumeShort << std::setprecision(2) << std::endl; std::cout << std::endl; // Close Long longOrderId = sendOrder[res.idExchLong](curl, params, "sell", fabs(btcUsed[res.idExchLong]), btcVec[res.idExchLong]->getLastBid()); // Close Short shortOrderId = sendOrder[res.idExchShort](curl, params, "buy", fabs(btcUsed[res.idExchShort]), btcVec[res.idExchShort]->getLastAsk()); // wait for the orders to be filled sleep(3.0); std::cout << "Waiting for the two orders to be filled..." << std::endl; while (!isOrderComplete[res.idExchLong](curl, params, longOrderId) || !isOrderComplete[res.idExchShort](curl, params, shortOrderId)) { sleep(3.0); } std::cout << "Done\n" << std::endl; longOrderId = 0; shortOrderId = 0; // market exited inMarket = false; // new balances for (unsigned i = 0; i < params.nbExch(); ++i) { newBalUsd[i] = getAvail[i](curl, params, "usd"); newBalBtc[i] = getAvail[i](curl, params, "btc"); } for (unsigned i = 0; i < params.nbExch(); ++i) { std::cout << "New balance on " << params.exchName[i] << ": \t"; std::cout << newBalUsd[i] << " USD (perf $" << newBalUsd[i] - balanceUsd[i] << "), "; std::cout << std::setprecision(6) << newBalBtc[i] << std::setprecision(2) << " BTC" << std::endl; } std::cout << std::endl; // update res with total balance res.befBalUsd = std::accumulate(balanceUsd.begin(), balanceUsd.end(), 0.0); res.aftBalUsd = std::accumulate(newBalUsd.begin(), newBalUsd.end(), 0.0); // update current balances with new values for (unsigned i = 0; i < params.nbExch(); ++i) { balanceUsd[i] = newBalUsd[i]; balanceBtc[i] = newBalBtc[i]; } // display performance std::cout << "ACTUAL PERFORMANCE: " << "$" << res.aftBalUsd - res.befBalUsd << " (" << res.totPerf() * 100.0 << "%)\n" << std::endl; // new csv line with result csvFile << res.id << "," << res.exchNameLong << "," << res.exchNameShort << "," << printDateTimeCsv(res.entryTime) << "," << printDateTimeCsv(res.exitTime); csvFile << "," << res.getLength() << "," << res.exposure * 2.0 << "," << res.befBalUsd << "," << res.aftBalUsd << "," << res.totPerf() << "\n"; csvFile.flush(); // send email if (params.sendEmail) { sendEmail(res, params); std::cout << "Email sent" << std::endl; } // delete result information res.clear(); // if "stop_after_exit" file exists then return std::ifstream infile("stop_after_exit"); if (infile.good()) { std::cout << "Exit after last trade (file stop_after_exit found)" << std::endl; stillRunning = false; } } } if (params.verbose) { std::cout << std::endl; } } // activities for this iteration terminated timeinfo->tm_sec = timeinfo->tm_sec + gapSec; currIteration++; if (currIteration >= debugMaxIteration) { std::cout << "Max iteration reached (" << debugMaxIteration << ")" <<std::endl; stillRunning = false; } } // delete Bitcoin objects for (unsigned i = 0; i < params.nbExch(); ++i) { delete(btcVec[i]); } json_decref(root); // close cURL curl_easy_cleanup(curl); curl_global_cleanup(); // close csv file csvFile.close(); return 0; }
int main(int argc, char** argv) { std::cout << "Blackbird Bitcoin Arbitrage" << std::endl; std::cout << "DISCLAIMER: USE THE SOFTWARE AT YOUR OWN RISK\n" << std::endl; std::locale mylocale(""); Parameters params("blackbird.conf"); if (!params.demoMode) { if (!params.useFullCash) { if (params.cashForTesting < 10.0) { std::cout << "WARNING: Minimum test cash recommended: $10.00\n" << std::endl; } if (params.cashForTesting > params.maxExposure) { std::cout << "ERROR: Test cash ($" << params.cashForTesting << ") is above max exposure ($" << params.maxExposure << ")\n" << std::endl; return -1; } } } getQuoteType getQuote[10]; getAvailType getAvail[10]; sendOrderType sendOrder[10]; isOrderCompleteType isOrderComplete[10]; getActivePosType getActivePos[10]; getLimitPriceType getLimitPrice[10]; int index = 0; if (params.bitfinexApi.empty() == false || params.demoMode == true) { params.addExchange("Bitfinex", params.bitfinexFees, params.bitfinexCanShort, true); getQuote[index] = Bitfinex::getQuote; getAvail[index] = Bitfinex::getAvail; sendOrder[index] = Bitfinex::sendOrder; isOrderComplete[index] = Bitfinex::isOrderComplete; getActivePos[index] = Bitfinex::getActivePos; getLimitPrice[index] = Bitfinex::getLimitPrice; index++; } if (params.okcoinApi.empty() == false || params.demoMode == true) { params.addExchange("OKCoin", params.okcoinFees, params.okcoinCanShort, true); getQuote[index] = OkCoin::getQuote; getAvail[index] = OkCoin::getAvail; sendOrder[index] = OkCoin::sendOrder; isOrderComplete[index] = OkCoin::isOrderComplete; getActivePos[index] = OkCoin::getActivePos; getLimitPrice[index] = OkCoin::getLimitPrice; index++; } if (params.bitstampClientId.empty() == false || params.demoMode == true) { params.addExchange("Bitstamp", params.bitstampFees, params.bitstampCanShort, true); getQuote[index] = Bitstamp::getQuote; getAvail[index] = Bitstamp::getAvail; sendOrder[index] = Bitstamp::sendOrder; isOrderComplete[index] = Bitstamp::isOrderComplete; getActivePos[index] = Bitstamp::getActivePos; getLimitPrice[index] = Bitstamp::getLimitPrice; index++; } if (params.geminiApi.empty() == false || params.demoMode == true) { params.addExchange("Gemini", params.geminiFees, params.geminiCanShort, true); getQuote[index] = Gemini::getQuote; getAvail[index] = Gemini::getAvail; sendOrder[index] = Gemini::sendOrder; isOrderComplete[index] = Gemini::isOrderComplete; getActivePos[index] = Gemini::getActivePos; getLimitPrice[index] = Gemini::getLimitPrice; index++; } if (params.krakenApi.empty() == false || params.demoMode == true) { params.addExchange("Kraken", params.krakenFees, params.krakenCanShort, true); getQuote[index] = Kraken::getQuote; getAvail[index] = Kraken::getAvail; sendOrder[index] = Kraken::sendOrder; isOrderComplete[index] = Kraken::isOrderComplete; getActivePos[index] = Kraken::getActivePos; getLimitPrice[index] = Kraken::getLimitPrice; index++; } if (params.itbitApi.empty() == false || params.demoMode == true) { params.addExchange("ItBit", params.itbitFees, params.itbitCanShort, false); getQuote[index] = ItBit::getQuote; getAvail[index] = ItBit::getAvail; // sendOrder[index] = ItBit::sendOrder; // isOrderComplete[index] = ItBit::isOrderComplete; getActivePos[index] = ItBit::getActivePos; getLimitPrice[index] = ItBit::getLimitPrice; index++; } if (params.btceApi.empty() == false || params.demoMode == true) { params.addExchange("BTC-e", params.btceFees, params.btceCanShort, false); getQuote[index] = BTCe::getQuote; getAvail[index] = BTCe::getAvail; // sendOrder[index] = BTCe::sendOrder; // isOrderComplete[index] = BTCe::isOrderComplete; getActivePos[index] = BTCe::getActivePos; getLimitPrice[index] = BTCe::getLimitPrice; index++; } if (params.sevennintysixApi.empty() == false || params.demoMode == true) { params.addExchange("796.com", params.sevennintysixFees, params.sevennintysixCanShort, true); getQuote[index] = SevenNintySix::getQuote; getAvail[index] = SevenNintySix::getAvail; sendOrder[index] = SevenNintySix::sendOrder; isOrderComplete[index] = SevenNintySix::isOrderComplete; getActivePos[index] = SevenNintySix::getActivePos; getLimitPrice[index] = SevenNintySix::getLimitPrice; index++; } if (index < 2) { std::cout << "ERROR: Blackbird needs at least two Bitcoin exchanges. Please edit the config.json file to add new exchanges\n" << std::endl; return -1; } std::string currDateTime = printDateTimeFileName(); std::string csvFileName = "blackbird_result_" + currDateTime + ".csv"; std::ofstream csvFile; csvFile.open(csvFileName.c_str(), std::ofstream::trunc); csvFile << "TRADE_ID,EXCHANGE_LONG,EXHANGE_SHORT,ENTRY_TIME,EXIT_TIME,DURATION,TOTAL_EXPOSURE,BALANCE_BEFORE,BALANCE_AFTER,RETURN\n"; csvFile.flush(); std::string logFileName = "blackbird_log_" + currDateTime + ".log"; std::ofstream logFile; logFile.open(logFileName.c_str(), std::ofstream::trunc); logFile.imbue(mylocale); logFile.precision(2); logFile << std::fixed; params.logFile = &logFile; logFile << "--------------------------------------------" << std::endl; logFile << "| Blackbird Bitcoin Arbitrage Log File |" << std::endl; logFile << "--------------------------------------------\n" << std::endl; logFile << "Blackbird started on " << printDateTime() << "\n" << std::endl; if (params.demoMode) { logFile << "Demo mode: trades won't be generated\n" << std::endl; } std::cout << "Log file generated: " << logFileName << "\nBlackbird is running... (pid " << getpid() << ")\n" << std::endl; // Vector of Bitcoin objects std::vector<Bitcoin*> btcVec; int num_exchange = params.nbExch(); // create Bitcoin objects for (int i = 0; i < num_exchange; ++i) { btcVec.push_back(new Bitcoin(i, params.exchName[i], params.fees[i], params.canShort[i], params.isImplemented[i])); } curl_global_init(CURL_GLOBAL_ALL); params.curl = curl_easy_init(); logFile << "[ Targets ]" << std::endl; logFile << " Spread Entry: " << params.spreadEntry * 100.0 << "%" << std::endl; logFile << " Spread Target: " << params.spreadTarget * 100.0 << "%" << std::endl; if (params.spreadEntry <= 0.0) { logFile << " WARNING: Spread Entry should be positive" << std::endl; } if (params.spreadTarget <= 0.0) { logFile << " WARNING: Spread Target should be positive" << std::endl; } logFile << std::endl; // store current balances logFile << "[ Current balances ]" << std::endl; double* balanceUsd = (double*)malloc(sizeof(double) * num_exchange); double* balanceBtc = (double*)malloc(sizeof(double) * num_exchange); for (int i = 0; i < num_exchange; ++i) { if (params.demoMode) { balanceUsd[i] = 0.0; balanceBtc[i] = 0.0; } else { balanceUsd[i] = getAvail[i](params, "usd"); balanceBtc[i] = getAvail[i](params, "btc"); } } // contains balances after a completed trade double* newBalUsd = (double*)malloc(sizeof(double) * num_exchange); double* newBalBtc = (double*)malloc(sizeof(double) * num_exchange); memset(newBalUsd, 0.0, sizeof(double) * num_exchange); memset(newBalBtc, 0.0, sizeof(double) * num_exchange); for (int i = 0; i < num_exchange; ++i) { logFile << " " << params.exchName[i] << ":\t"; logFile << balanceUsd[i] << " USD\t" << std::setprecision(6) << balanceBtc[i] << std::setprecision(2) << " BTC" << std::endl; if (balanceBtc[i] > 0.0300) { logFile << "ERROR: All BTC accounts must be empty before starting Blackbird" << std::endl; return -1; } } logFile << std::endl; logFile << "[ Cash exposure ]" << std::endl; if (params.demoMode) { logFile << " No cash - Demo mode" << std::endl; } else { if (params.useFullCash) { logFile << " FULL cash used!" << std::endl; } else { logFile << " TEST cash used\n Value: $" << params.cashForTesting << std::endl; } } logFile << std::endl; time_t rawtime; rawtime = time(NULL); struct tm* timeinfo; timeinfo = localtime(&rawtime); // wait the next gapSec seconds before starting time(&rawtime); timeinfo = localtime(&rawtime); while ((int)timeinfo->tm_sec % params.gapSec != 0) { sleep(0.01); time(&rawtime); timeinfo = localtime(&rawtime); } // main loop if (!params.verbose) { logFile << "Running..." << std::endl; } bool inMarket = false; int resultId = 0; Result res; res.clear(); unsigned currIteration = 0; bool stillRunning = true; time_t currTime; time_t diffTime; while (stillRunning) { currTime = mktime(timeinfo); time(&rawtime); diffTime = difftime(rawtime, currTime); // check if we are already too late if (diffTime > 0) { logFile << "WARNING: " << diffTime << " second(s) too late at " << printDateTime(currTime) << std::endl; // unsigned skip = (unsigned)ceil(diffTime / gapSec); // go to next iteration timeinfo->tm_sec = timeinfo->tm_sec + (ceil(diffTime / params.gapSec) + 1) * params.gapSec; currTime = mktime(timeinfo); sleep(params.gapSec - (diffTime % params.gapSec)); logFile << std::endl; } else if (diffTime < 0) { sleep(-difftime(rawtime, currTime)); // sleep until the next iteration } if (params.verbose) { if (!inMarket) { logFile << "[ " << printDateTime(currTime) << " ]" << std::endl; } else { logFile << "[ " << printDateTime(currTime) << " IN MARKET: Long " << res.exchNameLong << " / Short " << res.exchNameShort << " ]" << std::endl; } } for (int e = 0; e < num_exchange; ++e) { double bid = getQuote[e](params, true); double ask = getQuote[e](params, false); if (bid == 0.0) { logFile << " WARNING: " << params.exchName[e] << " bid is null, use previous one" << std::endl; } if (ask == 0.0) { logFile << " WARNING: " << params.exchName[e] << " ask is null, use previous one" << std::endl; } if (params.verbose) { logFile << " " << params.exchName[e] << ": \t" << bid << " / " << ask << std::endl; } btcVec[e]->updateData(bid, ask, 0.0); curl_easy_reset(params.curl); } if (params.verbose) { logFile << " ----------------------------" << std::endl; } // compute entry point if (!inMarket) { for (int i = 0; i < num_exchange; ++i) { for (int j = 0; j < num_exchange; ++j) { if (i != j) { if (checkEntry(btcVec[i], btcVec[j], res, params)) { // entry opportunity found res.exposure = std::min(balanceUsd[res.idExchLong], balanceUsd[res.idExchShort]); if (params.demoMode) { logFile << "INFO: Opportunity found but no trade will be generated (Demo mode)" << std::endl; break; } if (res.exposure == 0.0) { logFile << "WARNING: Opportunity found but no cash available. Trade canceled" << std::endl; break; } if (params.useFullCash == false && res.exposure <= params.cashForTesting) { logFile << "WARNING: Opportunity found but no enough cash. Need more than TEST cash (min. $" << params.cashForTesting << "). Trade canceled" << std::endl; break; } if (params.useFullCash) { res.exposure -= params.untouchedCash * res.exposure; // leave untouchedCash if (res.exposure > params.maxExposure) { logFile << "WARNING: Opportunity found but exposure ($" << res.exposure << ") above the limit" << std::endl; logFile << " Max exposure will be used instead ($" << params.maxExposure << ")" << std::endl; res.exposure = params.maxExposure; } } else { res.exposure = params.cashForTesting; // use test money } double volumeLong = res.exposure / btcVec[res.idExchLong]->getAsk(); double volumeShort = res.exposure / btcVec[res.idExchShort]->getBid(); double limPriceLong = getLimitPrice[res.idExchLong](params, volumeLong, false); double limPriceShort = getLimitPrice[res.idExchShort](params, volumeShort, true); if (limPriceLong - res.priceLongIn > params.priceDeltaLim || res.priceShortIn - limPriceShort > params.priceDeltaLim) { logFile << "WARNING: Opportunity found but not enough liquidity. Trade canceled" << std::endl; logFile << " Target long price: " << res.priceLongIn << ", Real long price: " << limPriceLong << std::endl; logFile << " Target short price: " << res.priceShortIn << ", Real short price: " << limPriceShort << std::endl; res.trailing[res.idExchLong][res.idExchShort] = -1.0; break; } inMarket = true; resultId++; // update result res.id = resultId; res.entryTime = currTime; res.printEntry(*params.logFile); res.maxSpread[res.idExchLong][res.idExchShort] = -1.0; res.minSpread[res.idExchLong][res.idExchShort] = 1.0; res.trailing[res.idExchLong][res.idExchShort] = 1.0; int longOrderId = 0; int shortOrderId = 0; // send orders longOrderId = sendOrder[res.idExchLong](params, "buy", volumeLong, btcVec[res.idExchLong]->getAsk()); shortOrderId = sendOrder[res.idExchShort](params, "sell", volumeShort, btcVec[res.idExchShort]->getBid()); // wait for the orders to be filled logFile << "Waiting for the two orders to be filled..." << std::endl; sleep(3.0); while (!isOrderComplete[res.idExchLong](params, longOrderId) || !isOrderComplete[res.idExchShort](params, shortOrderId)) { sleep(3.0); } logFile << "Done" << std::endl; longOrderId = 0; shortOrderId = 0; break; } } } if (inMarket) { break; } } if (params.verbose) { logFile << std::endl; } } // in market, looking to exit else if (inMarket) { if (checkExit(btcVec[res.idExchLong], btcVec[res.idExchShort], res, params, currTime)) { // exit opportunity found // check current exposure double* btcUsed = (double*)malloc(sizeof(double) * num_exchange); for (int i = 0; i < num_exchange; ++i) { btcUsed[i] = getActivePos[i](params); } double volumeLong = btcUsed[res.idExchLong]; double volumeShort = btcUsed[res.idExchShort]; double limPriceLong = getLimitPrice[res.idExchLong](params, volumeLong, true); double limPriceShort = getLimitPrice[res.idExchShort](params, volumeShort, false); if (res.priceLongOut - limPriceLong > params.priceDeltaLim || limPriceShort - res.priceShortOut > params.priceDeltaLim) { logFile << "WARNING: Opportunity found but not enough liquidity. Trade canceled" << std::endl; logFile << " Target long price: " << res.priceLongOut << ", Real long price: " << limPriceLong << std::endl; logFile << " Target short price: " << res.priceShortOut << ", Real short price: " << limPriceShort << std::endl; res.trailing[res.idExchLong][res.idExchShort] = 1.0; } else { res.exitTime = currTime; res.printExit(*params.logFile); int longOrderId = 0; int shortOrderId = 0; logFile << std::setprecision(6) << "BTC exposure on " << params.exchName[res.idExchLong] << ": " << volumeLong << std::setprecision(2) << std::endl; logFile << std::setprecision(6) << "BTC exposure on " << params.exchName[res.idExchShort] << ": " << volumeShort << std::setprecision(2) << std::endl; logFile << std::endl; // send orders longOrderId = sendOrder[res.idExchLong](params, "sell", fabs(btcUsed[res.idExchLong]), btcVec[res.idExchLong]->getBid()); shortOrderId = sendOrder[res.idExchShort](params, "buy", fabs(btcUsed[res.idExchShort]), btcVec[res.idExchShort]->getAsk()); // wait for the orders to be filled logFile << "Waiting for the two orders to be filled..." << std::endl; sleep(3.0); while (!isOrderComplete[res.idExchLong](params, longOrderId) || !isOrderComplete[res.idExchShort](params, shortOrderId)) { sleep(3.0); } logFile << "Done\n" << std::endl; longOrderId = 0; shortOrderId = 0; inMarket = false; // new balances for (int i = 0; i < num_exchange; ++i) { newBalUsd[i] = getAvail[i](params, "usd"); newBalBtc[i] = getAvail[i](params, "btc"); } for (int i = 0; i < num_exchange; ++i) { logFile << "New balance on " << params.exchName[i] << ": \t"; logFile << newBalUsd[i] << " USD (perf $" << newBalUsd[i] - balanceUsd[i] << "), "; logFile << std::setprecision(6) << newBalBtc[i] << std::setprecision(2) << " BTC" << std::endl; } logFile << std::endl; // update res with total balance for (int i = 0; i < num_exchange; ++i) { res.befBalUsd += balanceUsd[i]; res.aftBalUsd += newBalUsd[i]; } // update current balances with new values for (int i = 0; i < num_exchange; ++i) { balanceUsd[i] = newBalUsd[i]; balanceBtc[i] = newBalBtc[i]; } logFile << "ACTUAL PERFORMANCE: " << "$" << res.aftBalUsd - res.befBalUsd << " (" << res.totPerf() * 100.0 << "%)\n" << std::endl; csvFile << res.id << "," << res.exchNameLong << "," << res.exchNameShort << "," << printDateTimeCsv(res.entryTime) << "," << printDateTimeCsv(res.exitTime); csvFile << "," << res.getLength() << "," << res.exposure * 2.0 << "," << res.befBalUsd << "," << res.aftBalUsd << "," << res.totPerf() << "\n"; csvFile.flush(); if (params.sendEmail) { sendEmail(res, params); logFile << "Email sent" << std::endl; } res.clear(); std::ifstream infile("stop_after_exit"); if (infile.good()) { logFile << "Exit after last trade (file stop_after_exit found)" << std::endl; stillRunning = false; } } } if (params.verbose) { logFile << std::endl; } } timeinfo->tm_sec = timeinfo->tm_sec + params.gapSec; currIteration++; if (currIteration >= params.debugMaxIteration) { logFile << "Max iteration reached (" << params.debugMaxIteration << ")" <<std::endl; stillRunning = false; } } for (int i = 0; i < num_exchange; ++i) { delete(btcVec[i]); } curl_easy_cleanup(params.curl); curl_global_cleanup(); csvFile.close(); logFile.close(); return 0; }
////////////////////////////////////// //отправка сообщения в зависимости от установленных данных void Data::send() { //текст для вывода при отправке std::string logtext; //начальная установка отправителя / basic sender information and initialization senderInfo.senderName = senderName; senderInfo.server = server; senderInfo.senderMail = senderEmail; senderInfo.username = user; senderInfo.password = password; sender = new Sender(senderInfo); logtext += sender->get_log(); sender->initialise_files(this->fileatach.size()); for (int i=0; i<sender->nFiles; i++) { sender->fileNames[i] = fileatach[i]; } sender->load_files(); //////////////////////////////// //не отправляет сообщения, если нет текста. Если вы хотите это исправить уберите return if (message=="") { std::cerr << tr("No message!\n").toStdString(); SendEvent* pe = new SendEvent(); pe->setValue(SendEvent::SendData( tr("Nothing to send!\n").toStdString() ,100)); QApplication::postEvent(window, pe); return; } int counter=0; //по очереди для всех адресатов / for all receivers for (int i=0; i<(int)recvEmail.size(); i++) { std::string logtextPart; if (stoped) return; //выполнять следующие действия только если включен адрес / send only if address enabled if (!recvData[i].enabled) continue; //получение настоящего сообщения из шаблона / get message from template std::string mes = get_mes(recvData[i]); //отправка sendEmail(recvEmail[i],recvData[i].name,theme,mes,logtextPart); logtext+=logtextPart; //отправка информации в окно send / send event to sendWindow int size = enabledCount(); std::ostringstream omem; omem << "(" << counter++ << "/" << size << ")" << get_message_about_receiver(i); int percent = int(double(i)/double(size)*100); SendEvent* pe = new SendEvent(); std::cout << logtextPart; pe->setValue(SendEvent::SendData(omem.str(),logtext,percent)); QApplication::postEvent(window, pe); } std::ostringstream omem; //получение настоящего сообщения из шаблона / get message from template int size = enabledCount(); //сообщение об окончании передачи / send 'end of transmission' event to sendWindow omem << "(" << size << "/" << size << tr(") -- end of transmission").toStdString(); SendEvent* pe = new SendEvent(); pe->setValue(SendEvent::SendData(omem.str(),logtext,101)); QApplication::postEvent(window, pe); }
int main () { sendEmail(); return 0; }