I have been there - C++ resembles an onion, with layers upon layers of complexities and issues—until one day, it magically transforms into an apple.
Regarding nlohmann
, I chose not to use it because I try to stick with Boost
whenever it provides the same functionality. However, I am aware that nlohmann
is faster when it comes to parsing, so it's a valid choice depending on the requirements. My approach is to address problems using the tools I already have - thanks for mentioning that.
Overall, it appears that our solutions are quite similar; the primary difference is that my relay server is implemented entirely in C++. I employ multiple threads to manage communication with my data provider, and the data plugin interacts directly with these threads. In contrast to your approach, I opted to avoid Python entirely, as the Global Interpreter Lock (GIL) has caused issues for me in the past - numerous times, with no way around it. Despite the availability of coroutines and multithreading in Python, the GIL limits true multithreading. Given my need for multiple threads to handle communications, I found C++ to be a more suitable choice. With this setup, I have managed to keep the entire S&P 500 tickers updated in real-time on my system.
Regarding your observation:
AB doesn't request data if Ticker is not in any context. So for example I need minimum 1min bars. To keep GetQuoteEx() running, I put a 1min Exploration so the AB DB keeps bars updated.
If you have a chart with 20 symbols and no exploration, then EVEN if you send WM_USER_STREAMING_UPDATE, symbols not in context will NOT call GetQuoteEx().
(This is my observation, AB is behaving efficiently as Tomasz wrote)
I do not believe that is entirely accurate. While AmiBroker is efficient, it is not necessary to use exploration to keep the bars updated. If you are sending WM_USER_STREAMING_UPDATE
and the bars are not updating, it might be due to the "Real-time chart refresh interval" setting. This option controls how often GetQuoteEx
is called. If you set it to 0, the chart will update every time you send WM_USER_STREAMING_UPDATE
. Otherwise, if this setting is, for example, 5 seconds, then even if you send the message 100 times, the chart will only update once every 5 seconds.
You can find this setting here: Tools -> Preferences -> Intraday -> Real-time chart refresh interval
.
As for your issue with SendMessage
:
::SendMessage(..., (WPARAM)&g_aInfos[i].Name, (LPARAM)&g_aInfos[i]); // works
::SendMessage(..., (WPARAM)&ri->Name, (LPARAM)&ri); // does not
SendMessage
operates synchronously; the DLL code is blocked until WM_USER_STREAMING_UPDATE
is consumed on the MFC or AmiBroker side. Therefore, as long as ri
is defined within the same scope when SendMessage
is called, it should function correctly. If it does not, I would recommend verifying that ri
is valid and accessible at the time of the call.
If you download AmiBroker version 6.0 or 6.1 and set up Visual Studio for debugging, you can set a breakpoint where you send your WM_USER_STREAMING_UPDATE
to see what is happening with ri
. This can provide more insight into why the reference may not be working as expected.