MtSetPumpingMode

 
Hello,
Please tell me if I understand the usage for MtSetPumpingMode. I seem to be on MTAPI version number 372014 (3.72; although the single post with "MtSetPumpingMode" said he was on 3.85).
1) I need to create an HWND and its message pump.
2) I need to call MtSetPumpingMode one time for each (eventmsg) message I want to respond to in the message pump.
3) There is a list of allowed function calls while in pumping mode.

The documentation for MtSetPumpingMode does not list MtSendOrder in the list of allowed function calls while in pumping mode. Yet the documentation for MtSendOrder states, "If socket was transferred in pumping mode of the data...".
4) Is MtSendOrder an allowed function call while in pumping mode?
5) Are MtDeleteOrder, MtModifyOrder, MtCloseOrder, MtCloseByOrder allowed function calls while in pumping mode?
6) What is the complete list of allowed function calls while in pumping mode?

7) How do I turn pumping mode off? How do I end pumping? Do I simply send the eventmsg END_PUMPING in the function call MtSetPumpingMode? Can the message END_PUMPING be received in the message pump?

8) The documentation for MtSetWorkingDirectory states "Return codes are defined in the header file MetaTraderAPI.h". I think "MetaTraderAPI.h" is incorrect and should be "mtapi.h".

9) The documentation for MtRefreshSecurities states "...and it can be prohibited using the function MtGetSecurities...". I think "prohibited" is incorrect and should be "obtained" as in the relation between MtGetTrades and MtGetTradeRecords.

10 In MtGetSecurities, are the "accessible instruments" equal to the sum of "added symbols" and "hidden symbols"?

The variable names in mtapi.h are helpful.
11) May I have the English translation of the comments?

Please instruct me how to open and close a position.
12) Are all "OP_*" enums valid for "cmd" in struct SendOrderInfo?
13) What are OP_BALANCE and OP_CREDIT?

When I open a position with MtSendOrder, the SendOrderInfo struct requires a price, StopLoss "sl" and TakeProfit "tp".
14) Is there a relation to enums EXE_REQUEST and EXE_MARKET so that I get the current "price" and do not have to set "price" (or do I set "price" to 0.0)?
15) Is there a range I should set someplace for "price" so that the order gets accepted?
16) Depending upon my value for "price" and the market value (the actual current bid or ask) will my order be pending?
17) Can I set "sl" and/or "tp" to 0.0 in this struct?
18) Again, is MtModifyOrder allowed to be called during pumping mode if I need to set an original non-zero "sl" and/or "tp", then later adjust "sl" and/or "tp"?

Regards.
 
Did You see our examples and did You read function descriptions?
 
Yes. That is why I am asking if I understand. Some information in those documents seems to contradict.

However, regarding allowed function calls while in pumping mode, I have seen on this forum that I can have 2 sockets. One in pumping mode and one not.

But I still do not understand why there is eventmsg in MtSetPumpingMode.
Do I need to call MtSetPumpingMode one time for each (eventmsg) message I want to respond to in the message pump?

Can I turn pumping mode off by calling MtSetPumpingMode with eventmsg = END_PUMPING?

I understand that there may be a language barrier, but did you read my questions and comments in the above 18 issues?

I will be coding this weekend, so I may find out by trial and error.

Regards.
 
1. HWND needed for receiving messages from pump socket
2. SetPumpingMode needed for only one socket
3. what is incomprehensible?
===
Important! After transferring of the socket object in pumping mode of the data it is inadmissible
"not allowed" to request the server through the given socket any inquiries except for inquiries about
break on connection MtDisconnect. It is possible to call the following functions: MtGetTradeRecords,
MtGetSecurities, MtAddSymbol, MtHideSymbol, MtGetUpdatedTickInfo, MtGetLastNews, MtGetLastMail.
===
4. Do You see our examples?
To send order You need open socket, request for prices, send order, close socket.

You can open up to 10 sockets. Usually 1 socket should be open and be in the pumping mode. You receive data in passive mode from server via pumping socket. Did You read MetaTraderAPI(en).txt? All written exactly!
5, 6 are same as 4
7. Close socket
8. yes.
9. yes.
10. no. Symbols are added to and hidden from list of SELECTED symbols
11. no
12. no. from OP_ BUY to OP_SELL_STOP
13. balance/withdrawal and credit. There are broker's operations
14. see our examples. and see how client terminal works
15,16,17,18 - see examples and just try your solutions

FXCharts, MetaQuotes and MetaTrader3 are not supported
 
Thank you Slawa.
Some of my 18 issues were statements. Others were questions.
My confusion with #3 through #6 came from my assumption that I would be using only 1 socket. It is my understanding now, that if I want to use pumping mode to retrieve information, while at the same time placing orders, then I will need a minimum of 2 sockets.

19) Is there a benefit to using more than 2 sockets?
20) If so for #19, which scenarios?

I am still unclear on how to use pumping mode.
I perform:
api.WinsockStartup();
if((err=api.Connect(server, port))!=RET_OK)
if((err=api.Login(login, password))!=RET_OK)
api.SetPumpingMode(hWndPumpingMode, UPDATE_BIDASK);
But I do not receive any of the 5 messages (UPDATE_BIDASK, UPDATE_NEWS, UPDATE_TRADES, UPDATE_MAIL, END_PUMPING) in my WndProc for hWndPumpingMode.

I also tried:
if((err=api.RefreshSecurities())>RET_OK_NONE)
before api.SetPumpingMode(hWndPumpingMode, UPDATE_BIDASK);
and I at least have USDCHF in securities.dat. But no UPDATE_BIDASK was received when USDCHF changed in FXDirectDealer.

21) Is the single call to api.SetPumpingMode(hWndPumpingMode, UPDATE_BIDASK); sufficient to receive all 5 messages in the WndProc for hWndPumpingMode (i.e. destwnd)?
I assume YES from the answer to #2.

22) Is there a recommended conditional test I should perform on api.SetPumpingMode?
if((err=api.SetPumpingMode(hWndPumpingMode, UPDATE_BIDASK))!=RET_OK)
if((err=api.SetPumpingMode(hWndPumpingMode, UPDATE_BIDASK))>RET_OK_NONE)
When I display err after
err=api.SetPumpingMode(hWndPumpingMode, UPDATE_BIDASK);
I get the literal string "some error".

23) Similar to #11. May I have the Russian text and Unicode for the comments so that I can understand when to use RET_OK, RET_OK_NONE, etcetera?

24) I think I answered my own question #21 as YES. I was using
LRESULT CALLBACK WndPumpingModeProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
switch (message)
but I changed that to
switch (wParam)
and I seem to be receiving UPDATE_NEWS and UPDATE_BIDASK
Is this a correct approach?

Regards.
 
19. 1. You can work with more than 1 trade server
2. You can manage more than 1 account on the one server and simultaneously send orders for severe accounts
20. scenario depends from your algorithm

You pass your internal message (for instance WM_USER_4000 or some registered message) to the socket object. This message will be posted via PostMessage to your hwnd. UPDATE_BIDASK, UPDATE_NEWS, UPDATE_TRADES, UPDATE_MAIL, END_PUMPING passed as WPARAM. see our samples closely!

22. RET_OK only
23. There are russian equivalents only. for instance RET_OLD_VERSION, // old version of client terminal
24. message should be your internal message, see our examples please!

ON_REGISTERED_MESSAGE(g_PumpingMsg, OnPumpingMsg)
...
g_PumpingMsg = ::RegisterWindowMessage(_T("MetaTraderAPI_Pumping_Message"));
...
if ((err = m_api.SetPumpingMode(m_hWnd, g_PumpingMsg)) > RET_OK_NONE)
{
MessageBox(m_api.GetErrorDescription(err), _T("SetPumpingMode"), MB_OK | MB_ICONERROR);
return;
}

and etalon is
LRESULT CMetaTraderAPIExample2Dlg::OnPumpingMsg(WPARAM wParam, LPARAM lParam)
{
    switch (wParam)
    {
    case UPDATE_BIDASK:
        {
            CString sQuotes;
            sQuotes.Format(_T(" %d"), ++m_nQuotes);
            m_stQuotes.SetWindowText(sQuotes);
            //----
            int items;
            TickInfo* pti = m_api.GetUpdatedTickInfo(&items);
            for (int i = 0; i < items; i++)
            {
                int cnt = m_lstMarket.GetItemCount();
                for (int s = 0; s < cnt; s++)
                {
                    CString sSymbol = m_lstMarket.GetItemText(s, 0);
                    if (sSymbol == pti[i].symbol)
                    {
                        CString sFormat;
                        sFormat.Format(_T("%%.%dlf"), g_pSecs[m_lstMarket.GetItemData(s)].digits);
                        CString sPrice;
                        sPrice.Format(sFormat, pti[i].bid);
                        m_lstMarket.SetItemText(s, 1, sPrice);
                        sPrice.Format(sFormat, pti[i].ask);
                        m_lstMarket.SetItemText(s, 2, sPrice);
                    }
                }
            }
            //---- обновим открытые позиции
            if (m_bDoOrder == FALSE)
                UpdateTrades();
            //----
            break;
        }
    case UPDATE_NEWS:
        {
            int items;
            NewsTopic* pnt = m_api.GetLastNews(&items);
            for (int i = 0; i < items; i++)
            {
                int idx = m_lstNews.InsertItem(m_lstNews.GetItemCount(), pnt[i].ctm);
                m_lstNews.SetItemText(idx, 1, pnt[i].topic);
                m_lstNews.SetItemData(idx, pnt[i].newkey);
            }
            //----
            if (pnt != NULL)
                ::HeapFree(::GetProcessHeap(), 0, pnt);
            //----
            break;
        }
    case UPDATE_MAIL:
        {
            int err;
            char path[MAX_PATH];
            int len = MAX_PATH;
            if ((err = m_api.GetLastMail(path, &len)) > RET_OK_NONE)
            {
                m_status.InsertString(0, _T("Get last mail FAILED"));
                break;
            }
            //---- считаем заголовок
            FILE *In;
            if ((In = fopen(path,"rb")) != NULL)
            {
                MailBoxHeader mbh;
                if (fread(&mbh, sizeof(mbh), 1, In) == 1) 
                { 
                    mbh.from[63] = 0;
                    mbh.subject[127] = 0;
                    int idx;
                    tm *tt;
                    if ((tt = gmtime(&mbh.time)) != NULL) 
                    {
                        CString str;
                        str.Format("%04d.%02d.%02d %02d:%02d", 
                                1900+tt->tm_year, 1+tt->tm_mon, tt->tm_mday, 
                                tt->tm_hour, tt->tm_min);
                        idx = m_lstMail.InsertItem(m_lstMail.GetItemCount(), str);
                    }
                    else
                        idx = m_lstMail.InsertItem(m_lstMail.GetItemCount(), "unknown");
                    m_lstMail.SetItemText(idx, 1, mbh.from);
                    m_lstMail.SetItemText(idx, 2, mbh.subject);
                    m_lstMail.SetItemText(idx, 3, path);
                }
                fclose(In);
            }
            //----
            break;
        }
    case UPDATE_TRADES:
        {
            if (m_bDoOrder == FALSE)
            {
                UpdateTrades();
                UpdateAccountHistory();
            }
            break;
        }
    }
//----
    return 0;
}


 
Sorry. I did not study example 2 at all, since it is MFC. I only studied example 1 and 3 which have no pumping mode, so I thought it was not documented. I will study these examples and your code above.

Also, in case others are interested, example 1 and 3 work in Wine from winehq.com on Mac OSX nicely. Example 2 did not. MFC is probably not yet ported to Wine.

If you would convert that code above to an example 1 or example 3 style, I would really appreciate it.
I call SetPumpingMode only once via api.SetPumpingMode(hWndPumpingMode, UPDATE_BIDASK);
I have my WndPumpingModeProc with switch (wParam)
I am writing to a database the UPDATE_* signal I receive, but I do not call api.Get* yet.
However I do not automatically receive UPDATE_* signals.

I have 2 message pumps. The main 1 that was built by the VC++ Wizard, and 1 I made for hWndPumpingMode. When I tried to put it in the main one, the enum UPDATE_ #2 was already in use. To test if WndPumpingModeProc was working, I put this in the main WndProc:
case WM_RBUTTONDOWN:
::SetWindowText(hWnd, "WM_RBUTTONDOWN");
::SendMessage(hWndPumpingMode, WM_MBUTTONDBLCLK, (WPARAM)NULL, (LPARAM)NULL);
break;

And I put this in WndPumpingModeProc:
// Message handler for Pumping Mode.
LRESULT CALLBACK WndPumpingModeProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	if(myMt3Proxy == NULL) return 0;
	std::string wParamMessage = "default";
	std::string log;
	switch (wParam) 
	{
		case WM_MBUTTONDBLCLK:
			::SetWindowText(hWndFX_Proxy, "Sent WM_MBUTTONDBLCLK to WndPumpingModeProc");
			break;
		case UPDATE_BIDASK:
			::SetWindowText(hWndFX_Proxy, "UPDATE_BIDASK");
			wParamMessage = "UPDATE_BIDASK";
			break;
		case UPDATE_NEWS:
			::SetWindowText(hWndFX_Proxy, "UPDATE_NEWS");
			wParamMessage = "UPDATE_NEWS";
			break;
		case UPDATE_TRADES:
			::SetWindowText(hWndFX_Proxy, "UPDATE_TRADES");
			wParamMessage = "UPDATE_TRADES";
			break;
		case UPDATE_MAIL:
			::SetWindowText(hWndFX_Proxy, "UPDATE_MAIL");
			wParamMessage = "UPDATE_MAIL";
			break;
		case END_PUMPING:
			::SetWindowText(hWndFX_Proxy, "END_PUMPING");
			wParamMessage = "END_PUMPING";
			break;
		default:
			return DefWindowProc(hWnd, message, wParam, lParam);
	}
	if(wParamMessage.compare("default") != 0)
	{
		log = "INSERT INTO `logs` (`actor`, `log`) VALUES ('FX_Proxy', CONCAT('WndPumpingModeProc:', '" + wParamMessage + "'))";
		myMt3Proxy->fxLog(log);
	}
	return 0;
}



Although I right-click in the main GUI, I assume my WndPumpingModeProc is working because it processes the double-middle-click I send it.

But I do not automatically get UPDATE_* signals. I only get a database entry if I manually right-click in the main GUI window, instead of automatically.

Thank you.





 
Would anyone (a developer or someone from the community) be so kind as to convert the MetaTraderApiExample2, which uses MFC (from the MetaTrader 3 API) into a simple VC++ 6.0 Win32 example like MetaTraderApiExample1 or MetaTraderApiExample3 ?

Specifically, I just want to setup pumping mode using Win32 (non-MFC) in VC++ 6.0.

Maybe my problem is setting up a second message pump within a "Hello World" Win32 project.

I did change
"api.SetPumpingMode(hWndPumpingMode, UPDATE_BIDASK);"
to
"if((err = api.SetPumpingMode(hWndPumpingMode, g_PumpingMsg)) != RET_OK)"
after a call to
"g_PumpingMsg = ::RegisterWindowMessage(_T("MetaTraderAPI_Pumping_Message"));"

Also, I expanded my message pump to process/consume the data that may be on the socket (in case that is why I do not see any updates), but I still do not get a call to SetWindowText unless I actively click in the application window.

So I think I may not be setting up the Window which uses WndPumpingModeProc which would be similar to CMetaTraderAPIExample2Dlg::OnPumpingMsg.

Regards.
Reason: