std::string ForexConnectWrapper::getTradesAsYAML() {
    std::string rv;
    IO2GTableManager *tableManager = getLoadedTableManager();

    IO2GTradesTable *tradesTable = (IO2GTradesTable *)tableManager->getTable(Trades);
    IO2GTradeTableRow *tradeRow = NULL;
    IO2GTableIterator tableIterator;
    while (tradesTable->getNextRow(tableIterator, tradeRow)) {
        bool isLong = (strncmp(tradeRow->getBuySell(), "B", 1) == 0);
        double d = tradeRow->getOpenTime();
        std::string openDateTime;
        formatDate(d, openDateTime);

        IO2GOfferRow *offer = getTableRow<IO2GOfferRow, IO2GOffersTableResponseReader>(Offers, tradeRow->getOfferID(), &findOfferRowByOfferId, &getOffersReader);

        rv.append("- symbol: ").append(offer->getInstrument()).append("\n");
        offer->release();
        rv.append("  id: ").append(tradeRow->getTradeID()).append("\n");
        rv.append("  direction: ").append(isLong ? "long" : "short").append("\n");
        rv.append("  openPrice: ").append(double2str(tradeRow->getOpenRate())).append("\n");
        rv.append("  size: ").append(int2str(tradeRow->getAmount())).append("\n");
        rv.append("  openDate: ").append(openDateTime).append("\n");
        rv.append("  pl: ").append(double2str(tradeRow->getGrossPL())).append("\n");

        tradeRow->release();
    }

    tradesTable->release();
    tableManager->release();

    return rv;
}
void ForexConnectWrapper::closeMarket(const std::string tradeID, int amount) {
    IO2GTradeTableRow *trade = getTradeTableRow(tradeID);
    if (!trade) {
        std::stringstream ss;
        ss << "Could not find trade with ID = " << tradeID;
        log(ss.str());
        throw ss.str().c_str();
    }

    IO2GValueMap *valuemap = mRequestFactory->createValueMap();
    valuemap->setString(Command, O2G2::Commands::CreateOrder);
    valuemap->setString(OrderType, O2G2::Orders::TrueMarketClose);
    valuemap->setString(AccountID, sAccountID.c_str());
    valuemap->setString(OfferID, trade->getOfferID());
    valuemap->setString(TradeID, tradeID.c_str());
    valuemap->setString(BuySell, ( strncmp(trade->getBuySell(), "B", 1) == 0 ? O2G2::Sell : O2G2::Buy ) );
    trade->release();
    valuemap->setInt(Amount, amount);
    //valuemap->setString(CustomID, "Custom");

    IO2GRequest *request = mRequestFactory->createOrderRequest(valuemap);
    valuemap->release();

    TableListener *tableListener = new TableListener();
    tableListener->setRequestID(request->getRequestID());

    IO2GTableManager *tableManager = getLoadedTableManager();
    subscribeTableListener(tableManager, tableListener);

    Listener *ll = new Listener(session);
    IO2GResponse *response = ll->sendRequest(request);
    request->release();
    ll->release();

    if (!response) {
        std::stringstream ss;
        ss << "Failed to get response to closeMarket request " << tradeID << " " << amount;
        log(ss.str());
        throw ss.str().c_str();
    }

    tableListener->waitForTableUpdate();

    response->release();
    unsubscribeTableListener(tableManager, tableListener);
    tableListener->release();
    tableManager->release();
}
std::vector<TradeInfo> ForexConnectClient::getTrades()
{
    std::vector<TradeInfo> trades;
    TableHandler<Trades, IO2GTradesTable, IO2GTradeTableRow> handler(mpSession);
    std::map<std::string, std::string> offers = getOffers();
    while (handler.getNextRow())
    {
	IO2GTradeTableRow* tradeRow = handler.getRow();
	TradeInfo trade;
	const std::map<std::string, std::string>::const_iterator it = std::find_if(offers.begin(),
										   offers.end(),
										   boost::bind(&std::map<std::string, std::string>::value_type::second, _1) == tradeRow->getOfferID());
	if (it == offers.end())
	{
	    throw std::runtime_error("Could not get offer table row.");
	}
        trade.mInstrument = it->first;
	trade.mTradeID = tradeRow->getTradeID();
        trade.mBuySell = tradeRow->getBuySell();
        trade.mOpenRate = tradeRow->getOpenRate();
        trade.mAmount = tradeRow->getAmount();
        trade.mOpenDate = toPtime(tradeRow->getOpenTime());
        trade.mGrossPL = tradeRow->getGrossPL();
	trades.push_back(trade);
    }
    return trades;
}
IO2GTradeTableRow* ForexConnectWrapper::getTradeTableRow(std::string tradeID) {
        IO2GTableManager *tableManager = getLoadedTableManager();
        IO2GTradesTable *tradesTable = (IO2GTradesTable *)tableManager->getTable(::Trades);
        tableManager->release();

        IO2GTradeTableRow *tradeRow = NULL;
        IO2GTableIterator tableIterator;

        std::string sOfferID;

        while (tradesTable->getNextRow(tableIterator, tradeRow)) {
            if (tradeID == tradeRow->getTradeID()) {
                break;
            }
        }
        tradesTable->release();

        return tradeRow;
}
bool ForexConnectClient::closePosition(const std::string& tradeID)
{
    TableHandler<Trades, IO2GTradesTable, IO2GTradeTableRow> handler(mpSession);
    IO2GTradeTableRow *tradeRow = NULL;
    IO2GTableIterator tableIterator;
    while (true) {
	tradeRow = handler.getNextRow();
	if (!tradeRow) {
	    BOOST_LOG_TRIVIAL(error) << "Could not find trade with ID = " << tradeID;
	    return false;
	}
	if (tradeID == tradeRow->getTradeID()) {
	    break;
	}
    }
    O2G2Ptr<IO2GValueMap> valuemap = mpRequestFactory->createValueMap();
    valuemap->setString(Command, O2G2::Commands::CreateOrder);
    valuemap->setString(OrderType, O2G2::Orders::TrueMarketClose);
    valuemap->setString(AccountID, mAccountID.c_str());
    valuemap->setString(OfferID, tradeRow->getOfferID());
    valuemap->setString(TradeID, tradeID.c_str());
    valuemap->setString(BuySell, (strcmp(tradeRow->getBuySell(), O2G2::Buy) == 0) ? O2G2::Sell : O2G2::Buy);
    valuemap->setInt(Amount, tradeRow->getAmount());
    valuemap->setString(CustomID, "CloseMarketOrder");
    O2G2Ptr<IO2GRequest> request = mpRequestFactory->createOrderRequest(valuemap);
    if (!request)
    {
        BOOST_LOG_TRIVIAL(error) << mpRequestFactory->getLastError();
        return false;
    }
    mpResponseListener->setRequestID(request->getRequestID());
    mpSession->sendRequest(request);
    if (mpResponseListener->waitEvents())
    {
	Sleep(1000); // Wait for the balance update
	BOOST_LOG_TRIVIAL(info) << "Done!";
	return true;
    }
    BOOST_LOG_TRIVIAL(error) << "Response waiting timeout expired";
    return false;
}