Esempio n. 1
0
//Get unread news or all news for last year
const bool getNewsRSS(std::vector<WebsiteNews>& WebsiteNewsList)
{
    wxString RssContent;
    if (site_content(mmex::weblink::NewsRSS, RssContent) != wxURL_NOERR)
        return false;

    wxStringInputStream RssContentStream(RssContent);
    wxXmlDocument RssDocument;
    if (!RssDocument.Load(RssContentStream))
        return false;

    if (RssDocument.GetRoot()->GetName() != "rss")
        return false;

    const wxString news_last_read_date_str = Model_Setting::instance().GetStringSetting(INIDB_NEWS_LAST_READ_DATE, "");
    wxDate news_last_read_date;
    if (!news_last_read_date.ParseISODate(news_last_read_date_str))
        news_last_read_date = wxDateTime::Today().Subtract(wxDateSpan::Year());

    wxXmlNode* RssRoot = RssDocument.GetRoot()->GetChildren()->GetChildren();
    while (RssRoot)
    {
        if (RssRoot->GetName() == "item")
        {
            WebsiteNews website_news;
            wxXmlNode* News = RssRoot->GetChildren();
            while (News)
            {
                wxString ElementName = News->GetName();

                if (ElementName == "title")
                    website_news.Title = News->GetChildren()->GetContent();
                else if (ElementName == "link")
                    website_news.Link = News->GetChildren()->GetContent();
                else if (ElementName == "description")
                    website_news.Description = News->GetChildren()->GetContent();
                else if (ElementName == "pubDate")
                {
                    wxDateTime Date;
                    const wxString DateString = News->GetChildren()->GetContent();
                    if (!DateString.IsEmpty())
                        Date.ParseDate(DateString);
                    if (!Date.IsValid())
                        Date = wxDateTime::Today().Subtract(wxDateSpan::Year()); //Seems invalid date, mark it as 1 year old
                    website_news.Date = Date;
                }
                News = News->GetNext();
            }
            wxLogDebug("%s - %s", news_last_read_date.FormatISODate(), website_news.Date.FormatISODate());
            if (news_last_read_date.IsEarlierThan(website_news.Date))
                WebsiteNewsList.push_back(website_news);
        }
        RssRoot = RssRoot->GetNext();
    }

    if (WebsiteNewsList.size() == 0)
        return false;

    return true;
}
const bool mmHomePagePanel::getNewsRSS(std::vector<WebsiteNews>& WebsiteNewsList)
{
    wxString RssContent;
    if (site_content(mmex::weblink::NewsRSS, RssContent) != wxURL_NOERR)
        return false;

    wxStringInputStream RssContentStream(RssContent);
    wxXmlDocument RssDocument;
    if (!RssDocument.Load(RssContentStream))
        return false;

    if (RssDocument.GetRoot()->GetName() != "rss")
        return false;

    wxXmlNode* RssRoot = RssDocument.GetRoot()->GetChildren()->GetChildren();
    while (RssRoot)
    {
        if (RssRoot->GetName() == "item")
        {
            WebsiteNews website_news;
            wxXmlNode* News = RssRoot->GetChildren();
            while(News)
            {
                wxString ElementName = News->GetName();

                if (ElementName == "title")
                    website_news.Title = News->GetChildren()->GetContent();
                else if (ElementName == "link")
                    website_news.Link = News->GetChildren()->GetContent();
                else if (ElementName == "description")
                    website_news.Description = News->GetChildren()->GetContent();
                else if (ElementName == "pubDate")
                {
                    wxDateTime Date = wxDateTime::Today();
                    wxString DateString = News->GetChildren()->GetContent();
                    if (!DateString.IsEmpty())
                        Date.ParseDate(DateString);
                    if (!Date.IsValid())
                        Date = wxDateTime::Today();
                    website_news.Date = Date;
                }
                News = News->GetNext();
            }
            WebsiteNewsList.push_back(website_news);
        }
        RssRoot = RssRoot->GetNext();
    }

    if (WebsiteNewsList.size() == 0)
        return false;

    return true;
}
bool mmMainCurrencyDialog::HistoryDownloadBce()
{
    wxString XmlContent;
    if (site_content(mmex::weblink::BceCurrencyHistory, XmlContent) != wxURL_NOERR)
        return false;

    wxStringInputStream XmlContentStream(XmlContent);
    wxXmlDocument XmlDocument;
    if (!XmlDocument.Load(XmlContentStream))
        return false;
    if (XmlDocument.GetRoot()->GetName() != "gesmes:Envelope")
        return false;

    wxXmlNode* XmlRoot = XmlDocument.GetRoot()->GetChildren();
    while (XmlRoot->GetName() != "Cube")
        XmlRoot = XmlRoot->GetNext();
    if (XmlRoot->GetName() != "Cube")
        return false;

    double Rate;
    wxDateTime HistoryDate;
    XmlRoot = XmlRoot->GetChildren(); //Go inside <Cube>
    while (XmlRoot) //<Cube time="2015-07-03">
    {
        HistoryDate.ParseDate(XmlRoot->GetAttribute("time"));
        CurrencyHistoryRate CurrencyHistory;
        wxXmlNode* XmlRate = XmlRoot->GetChildren();
        while (XmlRate) //<Cube currency="USD" rate="1.1096"/>
        {
            CurrencyHistory.BaseCurrency = "EUR";
            CurrencyHistory.Date = HistoryDate;
            CurrencyHistory.Currency = XmlRate->GetAttribute("currency");
            XmlRate->GetAttribute("rate").ToDouble(&Rate);
            CurrencyHistory.Rate = Rate;

            _BceCurrencyHistoryRatesList.push_back(CurrencyHistory);
            XmlRate = XmlRate->GetNext();
        }
        XmlRoot = XmlRoot->GetNext();
    }

    if (_BceCurrencyHistoryRatesList.size() == 0)
        return false;

    return true;
}
Esempio n. 4
0
void mmStockDialog::OnHistoryDownloadButton(wxCommandEvent& /*event*/)
{
    /*
    Example stock history download:
    https://code.google.com/p/yahoo-finance-managed/wiki/csvHistQuotesDownload
    */

    if (m_stock->SYMBOL.IsEmpty())
        return;

    const wxDateTime& StartDate = Model_Stock::PURCHASEDATE(m_stock);
    wxDateTime EndDate = wxDate::Today();
    const wxTimeSpan time = EndDate - StartDate;
    long intervalMonths = EndDate.GetMonth() - StartDate.GetMonth()
        + 12 * (EndDate.GetYear() - StartDate.GetYear())
        - (EndDate.GetDay() < StartDate.GetDay());

    //Define frequency
    enum { DAILY, WEEKLY, MONTHLY };
    wxArrayString FreqStrs;
    FreqStrs.Add(_("Days"));
    FreqStrs.Add(_("Weeks"));
    if (intervalMonths > 0) FreqStrs.Add(_("Months"));

    int freq = wxGetSingleChoiceIndex(_("Specify type frequency of stock history")
        , _("Stock History Update"), FreqStrs);

    long interval = 0;
    switch (freq)
    {
    case DAILY: interval = time.GetDays(); break;
    case WEEKLY: interval = time.GetWeeks(); break;
    case MONTHLY: interval = intervalMonths; break;
    default: return;
    }

    int nrPrices = (int) wxGetNumberFromUser(_("Specify how many stock history prices download from purchase date")
        , wxString::Format(_("Number of %s:"), FreqStrs.Item(freq).Lower()), _("Stock History Update")
        , interval, 1L, 9999L, this, wxDefaultPosition);

    if (nrPrices <= 0)
    {
        mmErrorDialogs::MessageInvalid(this, FreqStrs[freq]);
        return;
    }
    else
    {
        switch (freq)
        {
        case DAILY: EndDate = wxDate(StartDate).Add(wxDateSpan::Days(nrPrices)); break;
        case WEEKLY: EndDate = wxDate(StartDate).Add(wxDateSpan::Weeks(nrPrices)); break;
        case MONTHLY: EndDate = wxDate(StartDate).Add(wxDateSpan::Months(nrPrices)); break;
        default: break;
        }
    }

    if (EndDate > wxDate::Today())
    {
        mmErrorDialogs::MessageWarning(this, _("End date is in the future\nQuotes will be updated until today")
            , _("Stock History Error"));
        EndDate = wxDate::Today();
    }

    wxString CSVQuotes;
    wxString URL = mmex::weblink::YahooQuotesHistory;
    URL += m_stock->SYMBOL;
    URL += wxString::Format("&a=%i", StartDate.GetMonth());
    URL += wxString::Format("&b=%i", StartDate.GetDay());
    URL += wxString::Format("&c=%i", StartDate.GetYear());
    URL += wxString::Format("&d=%i", EndDate.GetMonth());
    URL += wxString::Format("&e=%i", EndDate.GetDay());
    URL += wxString::Format("&f=%i", EndDate.GetYear());
    switch (freq)
    {
    case DAILY: URL += "&g=d"; break;
    case WEEKLY: URL += "&g=w"; break;
    case MONTHLY: URL += "&g=m"; break;
        default: break;
    }
    URL += "&ignore=.csv";
    wxLogDebug("Start Date:%s End Date:%s URL:%s", StartDate.FormatISODate(), EndDate.FormatISODate(), URL);

    int err_code = site_content(URL, CSVQuotes);
    if (err_code != wxURL_NOERR)
    {
        if (err_code == -1) CSVQuotes = _("Stock history not found!");
        mmErrorDialogs::MessageError(this, CSVQuotes, _("Stock History Error"));
        return;
    }

    double dPrice;
    wxString dateStr;
    Model_StockHistory::Data *data;

    wxStringTokenizer tkz(CSVQuotes, "\r\n");
    Model_StockHistory::instance().Savepoint();
    while (tkz.HasMoreTokens())
    {
        wxStringTokenizer tkzSingleLine(tkz.GetNextToken(), ",");
        std::vector<wxString> tokens;
        while (tkzSingleLine.HasMoreTokens())
        {
            const wxString& token = tkzSingleLine.GetNextToken();
            tokens.push_back(token);
        }

        if (tokens[0].Contains("-"))
        {
            dateStr = tokens[0];
            tokens[6].ToDouble(&dPrice);

            if (Model_StockHistory::instance().find(
                    Model_StockHistory::SYMBOL(m_stock->SYMBOL),
                    Model_StockHistory::DB_Table_STOCKHISTORY_V1::DATE(dateStr)
                ).size() == 0
                && dPrice > 0)
            {
                data = Model_StockHistory::instance().create();
                data->SYMBOL = m_stock->SYMBOL;
                data->DATE = dateStr;
                data->VALUE = dPrice;
                data->UPDTYPE = Model_StockHistory::ONLINE;
                Model_StockHistory::instance().save(data);
            }
        }
    }
    Model_StockHistory::instance().ReleaseSavepoint();
    showStockHistory();
}
Esempio n. 5
0
/*** Trigger a quote download ***/
bool mmStocksPanel::onlineQuoteRefresh(wxString& sError)
{
    if(listCtrlAccount_->m_stocks.size() < 1)
    {
        sError = _("Nothing to update");
        return false;
    }

    //Symbol, (Amount, Name)
    std::map<wxString, std::pair<double, wxString> > stocks_data;
    wxString site = "";

    for (const auto &stock : listCtrlAccount_->m_stocks)
    {
        const wxString symbol = stock.SYMBOL.Upper();
        if (!symbol.IsEmpty())
        {
            if (stocks_data.find(symbol) == stocks_data.end())
            {
                stocks_data[symbol] = std::make_pair(stock.CURRENTPRICE, "");
                site << symbol << "+";
            }
        }
    }
    if (site.Right(1).Contains("+")) site.RemoveLast(1);

    //Sample: http://finance.yahoo.com/d/quotes.csv?s=SBER.ME+GAZP.ME&f=sl1c4n&e=.csv
    //Sample CSV: "SBER.ME",85.49,"RUB","SBERBANK"
    site = wxString::Format(mmex::weblink::YahooQuotes, site);

    refresh_button_->SetBitmapLabel(wxBitmap(wxImage(led_yellow_xpm).Scale(16,16)));
    stock_details_->SetLabelText(_("Connecting..."));
    wxString sOutput;

    int err_code = site_content(site, sOutput);
    if (err_code != wxURL_NOERR)
    {
        sError = sOutput;
        return false;
    }

    //--//
    wxString StockSymbolWithSuffix, sName, StockQuoteCurrency;
    double dPrice = 0.0;

    wxStringTokenizer tkz(sOutput, "\r\n");
    while (tkz.HasMoreTokens())
    {
        const wxString csvline = tkz.GetNextToken();
        StockSymbolWithSuffix = "";
        StockQuoteCurrency = "";
        wxRegEx pattern("\"([^\"]+)\",([^,][0-9.]+),\"([^\"]*)\",\"([^\"]*)\"");
        if (pattern.Matches(csvline))
        {
            StockSymbolWithSuffix = pattern.GetMatch(csvline, 1);
            pattern.GetMatch(csvline, 2).ToDouble(&dPrice);
            StockQuoteCurrency = pattern.GetMatch(csvline, 3);
            sName = pattern.GetMatch(csvline, 4);
        }

        bool updated = !StockSymbolWithSuffix.IsEmpty();

        /* HACK FOR GBP
        http://sourceforge.net/p/moneymanagerex/bugs/414/
        http://sourceforge.net/p/moneymanagerex/bugs/360/
        1. If the share has GBp as currency, its downloaded value in pence
        2. If the share has another currency, we don't need to modify the price
        */

        if (updated && dPrice > 0)
        {
            if (StockQuoteCurrency == "GBp")
                dPrice = dPrice / 100;
            stocks_data[StockSymbolWithSuffix].first = dPrice;
            stocks_data[StockSymbolWithSuffix].second = sName;
            sError << wxString::Format(_("%s\t -> %s\n")
                , StockSymbolWithSuffix, wxString::Format("%0.4f", dPrice));
        }
    }

    for (auto &s: listCtrlAccount_->m_stocks)
    {
        std::map<wxString, std::pair<double, wxString> >::const_iterator it = stocks_data.find(s.SYMBOL.Upper());
        if (it == stocks_data.end()) continue;
        dPrice = it->second.first;

        s.CURRENTPRICE = dPrice;
        s.VALUE = dPrice * s.NUMSHARES;
        if (s.STOCKNAME.empty()) s.STOCKNAME = it->second.second;
        Model_Stock::instance().save(&s);
    }

    // Now refresh the display
    int selected_id = -1;
    if (listCtrlAccount_->get_selectedIndex() > -1)
        selected_id = listCtrlAccount_->m_stocks[listCtrlAccount_->get_selectedIndex()].STOCKID;
    listCtrlAccount_->doRefreshItems(selected_id);

    // We are done!
    LastRefreshDT_       = wxDateTime::Now();
    StocksRefreshStatus_ = true;
    refresh_button_->SetBitmapLabel(wxBitmap(wxImage(led_green_xpm).Scale(16,16)));

    strLastUpdate_.Printf(_("%s on %s"), LastRefreshDT_.FormatTime()
        , LastRefreshDT_.FormatDate());
    Model_Infotable::instance().Set("STOCKS_LAST_REFRESH_DATETIME", strLastUpdate_);

    return true;
}
bool mmMainCurrencyDialog::OnlineUpdateCurRate(int curr_id, bool hide)
{
    wxString base_symbol = wxEmptyString;
    wxString msg = wxEmptyString;
    wxString site = mmex::weblink::YahooQuotes;
    bool ok = true;

    Model_Currency::Data * base_currency = Model_Currency::GetBaseCurrency();
    if (base_currency)
        base_symbol = base_currency->CURRENCY_SYMBOL.Upper();

    ok = !base_symbol.empty();
    if (!ok)
        msg = _("Could not find base currency symbol!");

    auto currencies = Model_Currency::instance().all();
    wxString sOutput;
    if (ok)
    {
        wxString buffer = wxEmptyString;
        for (const auto &currency : currencies)
        {
            const wxString symbol = currency.CURRENCY_SYMBOL.Upper();
            if (curr_id > 0 && currency.CURRENCYID != curr_id) continue;
            if (!symbol.IsEmpty()) buffer << symbol << base_symbol << "=X+";
        }
        if (buffer.Right(1).Contains("+")) buffer.RemoveLast(1);
        site = wxString::Format(site, buffer);

        int err_code = site_content(site, sOutput);
        if (err_code != wxURL_NOERR)
        {
            msg = sOutput;
            ok = false;
        }
    }

    if (ok)
    {
        wxString CurrencySymbol, sName;
        double dRate = 1;

        std::map<wxString, std::pair<double, wxString> > currency_data;

        // Break it up into lines
        wxStringTokenizer tkz(sOutput, "\r\n");

        while (tkz.HasMoreTokens())
        {
            wxString csvline = tkz.GetNextToken();

            wxRegEx pattern("\"(...)...=X\",([^,][0-9.]+),\"([^\"]*)\",\"([^\"]*)\"");
            if (pattern.Matches(csvline))
            {
                CurrencySymbol = pattern.GetMatch(csvline, 1);
                pattern.GetMatch(csvline, 2).ToDouble(&dRate);
                sName = pattern.GetMatch(csvline, 4);
                currency_data[CurrencySymbol] = std::make_pair(dRate, sName);
            }
        }

        msg = _("Currency rate updated");
        msg << "\n\n";

        Model_CurrencyHistory::instance().Savepoint();
        for (auto &currency : currencies)
        {
            if (!cbShowAll_->IsChecked() && !Model_Account::is_used(currency)) continue;

            const wxString currency_symbol = currency.CURRENCY_SYMBOL.Upper();
            if (!currency_symbol.IsEmpty())
            {
                if (currency_data.find(currency_symbol) != currency_data.end())
                {
                    msg << wxString::Format("%s\t: %0.6f -> %0.6f\n"
                        , currency_symbol, currency.BASECONVRATE, currency_data[currency_symbol].first);
                    currency.BASECONVRATE = currency_data[currency_symbol].first;
                    if (base_symbol == currency_symbol)
                        continue;
                    Model_CurrencyHistory::instance().addUpdate(currency.CURRENCYID,
                        wxDateTime::Today(), currency.BASECONVRATE, Model_CurrencyHistory::ONLINE);
                    Model_Currency::instance().save(&currency);
                }
                else
                {
                    if (curr_id < 0)
                        msg << wxString::Format(_("%s\t: %s\n"), currency_symbol, _("Invalid value "));
                }
            }
        }

        //Model_Currency::instance().save(currencies);  BASECONVRATE IS FIXED AND USED IF HISTORY NOT FOUND 
        Model_CurrencyHistory::instance().ReleaseSavepoint();

        wxMessageDialog msgDlg(this, msg, _("Currency rate updated"));
        if (!hide)
            msgDlg.ShowModal();
        fillControls();
        ShowCurrencyHistory();
    }
    else
    {
        wxMessageDialog msgDlg(this, msg, _("Error"), wxOK | wxICON_ERROR);
        msgDlg.ShowModal();
    }
    return ok;
}