In MQL4, I know how to set stopLoss and takeProfit.
However, I would like to do something else when such events actually take place.
Is there any event listener associated with such?
Unfortunately, there are no trade-events in MQL4.
However, it can be simulated as such ( logic-only-code, may not compile ):
#property copyright "No copyright, can be used freely, Joseph Lee"
#property link "https://www.facebook.com/joseph.fhlee"
int vaiTicketList[];
int start() {
int viIndex;
// -----------------------------------------------------------
// EVENT CHECK SECTION:
// Check vaiTicketList (populated in the previous cycle) to see if
// each of the (previously) open ticket is still currently open.
// -----------------------------------------------------------
for( viIndex=0; viIndex<ArrayRange(vaiTicketList,0); viIndex++) {
// Check if Ticket which was previously opened in the last
// cycle is no longer open now.
if(!OrderSelect( vaiTicketList[viIndex], SELECT_BY_TICKET ) ) {
// -----------------------------------
// EVENT CATEGORIZATION:
// -----------------------------------
// Handle possible events here:
// -- Close event: (OrderSelect( ticket, SELECT_BY_TICKET, MODE_HISTORY) == true)
if( OrderSelect(vaiTicketList[viIndex], SELECT_BY_TICKET, MODE_HISTORY) )
eventTrade_Closed( vaiTicketList[viIndex] );
// -- StopLoss ( Buy: When OrderClosePrice() <= OrderStopLoss(),
// Sell: When OrderClosePrice() >= OrderStopLoss() )
// -- TakeProfit (Buy: When OrderClosePrice() >= OrderTakeProfit(),
// Sell: When OrderClosePrice() <= OrderTakeProfit() )
// -- Expiration, Cancel, etc, etc
}
}
// -----------------------------------------------------------
// Store a list of all currently OPEN trade tickets into array.
// This is used to be compared in the next tick.
// -----------------------------------------------------------
ArrayResize( vaiTicketList, OrdersTotal() );
for ( viIndex=0; viIndex<OrdersTotal(); viIndex++) {
if(OrderSelect(viIndex, SELECT_BY_POS, MODE_TRADES)) {
vaiTicketList[viIndex] = OrderTicket();
}
}
// -----------------------------------------------------------
};
// ---------------------------------------
// This is the Trade Close event handler
// ---------------------------------------
bool eventTrade_Closed( int pviTicket ) {
bool vbIsEventBubble = true;
// Do something here to handle the event.
// FEATURE: vbIsEventBubble TRUE will allow event bubbles.
return( vbIsEventBubble);
}
bool eventTrade_otherPossibleEvents1() {};
bool eventTrade_otherPossibleEvents2() {};
bool eventTrade_otherPossibleEvents3() {};
bool eventTrade_otherPossibleEventsN() {};
Something along this line. Hope it helps.
you can use OrdersHistoryTotal() with a static variable to recognize this event. if this value is increased means that a position has closed.
No, there is no such direct event listener.
But:
we may create one such and test it's activation on an OnTick() event-bound handler basis.
void OnTick(){ // MQL4 system-initiated event-handler
// ---
myOnTickStealthTP_EventMONITOR(); // my Event Monitor
myOnTickStealthSL_EventMONITOR(); // my Event Monitor
// ---
// other code
}
Extending, upon not2qubit's conjecture ( irrespective how on-topic, weak or wrong one might consider that ):
You just posted an artificial non-existing function. What good is that? It would have been far more helpful if you could have provided as partially working code snippet for what you suggest. Recalling that most users of MQL4 are not programmers. – not2qubit 47 mins ago
void myOnTickStealthTP_EventMONITOR(){ // HERE put everything,
// TP_Event // what the "something else"
// ( when such events
// actually take place
// )
// meant - that's fair, isn't it ?
...
}
void myOnTickStealthSL_EventMONITOR(){ // HERE put everything,
// SL_Event // what the "something else"
// ( when such events
// actually take place
// )
// meant - that's fair, isn't it ?
...
}
Related
When annotation an observer method with AFTER_SUCCESS, the events are received in the reverse order they actually have been fired during the transaction.
Example pseudo code:
#Transactional
void test(){
pushEvent.fire( new PushEvent(10) );
pushEvent.fire( new PushEvent(20) );
pushEvent.fire( new PushEvent(30) );
}
Observer:
void onPushEvent( #Observes( during = TransactionPhase.AFTER_SUCCESS ) PushEvent event ){
System.out.println(event.getValue())
}
Unexpected, but observed result:
30
20
10
Can this be changed?
Fixed this in my project with a thread-local buffer of events which gets flushed on AFTER_SUCCESS and replays the events in the order they appeared in first place
ThreadLocal<List<PushEvent>> threadEventBufferHolder = ThreadLocal.withInitial( ArrayList::new );
void onPushEvent( #Observes( during = TransactionPhase.IN_PROGRESS ) PushEvent event ){
threadEventBufferHolder.get().add( event );
}
void onPushEventFailure( #Observes( during = TransactionPhase.AFTER_FAILURE ) PushEvent event ){
buffer.clear();
}
void onPushEventCommit( #Observes( during = TransactionPhase.AFTER_SUCCESS ) PushEvent event ){
List<PushEvent> buffer = threadEventBufferHolder.get();
buffer.forEach( this::doPrintlnValue );
buffer.clear();
}
Unrelated code removed for easier reading
Following this answer, I'm doing consecutive ray casts:
m_rayCaster = new Qt3DRender::QRayCaster(m_scene->rootEntity());
m_rayCaster->setRunMode(Qt3DRender::QAbstractRayCaster::SingleShot);
m_scene->rootEntity()->addComponent(m_rayCaster);
I have these slots to handle whether and when next consecutive ray cast test should be done:
QObject::connect(m_rayCaster, &Qt3DRender::QRayCaster::hitsChanged, this, &RayCastHandler::handleRayCasterHits);
QObject::connect(m_rayCaster, &Qt3DCore::QNode::enabledChanged, this, &RayCastHandler::handleRayCasterEnabledChange);
QObject::connect(this, &RayCastHandler::isPreviousTestDoneChanged, this, &RayCastHandler::handleIsPreviousTestDoneChange);
QObject::connect(this, &RayCastHandler::isNextTestRequiredChanged, this, &RayCastHandler::handleIsNextTestRequiredChange);
The slots set the conditions and check them:
void RayCastHandler::handleRayCasterHits(const Qt3DRender::QAbstractRayCaster::Hits hits)
{
analyzeHits(hits);
bool required = isNextTestRequired(/* according to m_testCounter, m_testsTotal, ... */);
emit isNextTestRequiredChanged(required);
emit isPreviousTestDoneChanged(true);
return;
}
void RayCastHandler::handleRayCasterEnabledChange(const bool enabled)
{
m_isRayCasterEnabled = enabled;
triggerNextTestIfAllConditionsAreTrue();
return;
}
void RayCastHandler::handleIsPreviousTestDoneChange(const bool done)
{
m_isPreviousTestDone = done;
triggerNextTestIfAllConditionsAreTrue();
return;
}
void RayCastHandler::handleIsNextTestRequiredChange(const bool required)
{
m_isNextTestRequired = required;
if (!m_isNextTestRequired)
emit rayCastResultsChanged(m_collisions);
triggerNextTestIfAllConditionsAreTrue();
return;
}
The code which checks if next ray cast test is required:
bool RayCastHandler::isNextTestRequired(int &testCounter, const int &testsTotal)
{
testCounter++;
if (testCounter >= testsTotal) {
return false;
}
return true;
}
And finally, the function which checks all the conditions to trigger next ray cast test is:
bool RayCastHandler::triggerNextTestIfAllConditionsAreTrue()
{
if (m_isPreviousTestDone && m_isNextTestRequired && m_isRayCasterEnabled) {
triggerTest(/* Will trigger next ray cast test */);
m_isPreviousTestDone = false;
m_isNextTestRequired = false;
m_isRayCasterEnabled = false;
}
}
The code works fine, but after casting a few consecutive rays, it stops.
By logging to console, I observe that the m_rayCaster looks to be enabled/disabled randomly. I mean sometimes after finishing a ray cast test, it disables itself, and sometimes it enables itself! I wonder if anybody can introduce a reference on Qt3DRender::QRayCaster enabling/disabling logic. I looked at its source code a bit, I wonder which section of source code might help me to figure out.
Just wanted to share my observations:
I simplified the code by keeping only two signal-slot connections:
QObject::connect(m_rayCaster, &Qt3DRender::QRayCaster::hitsChanged, this, &RayCastHandler::handleRayCasterHits);
QObject::connect(m_rayCaster, &Qt3DCore::QNode::enabledChanged, this, &RayCastHandler::handleRayCasterEnabledChange);
One slot analyzes the hits of ray-caster:
void RayCastHandler::handleRayCasterHits(const Qt3DRender::QAbstractRayCaster::Hits hits)
{
analyzeHits( ... , hits);
return;
}
The other slot runs the next consecutive ray-cast test, if ray-caster has disabled itself:
void RayCastHandler::handleRayCasterEnabledChange(const bool enabled)
{
// When the component disables itself, it is ready for the next ray-cast test
if (!enabled) {
bool required = isNextTestRequired( ... );
if (required)
triggerTest( ... );
else
// Send final ray-cast results by a signal, if next test is NOT needed
emit rayCastResultsChanged( ... );
}
return;
}
The above code works as long as I trigger ray-cast tests with a time-delay. Sometimes I have to increase the above delay time to make it work. But at least it works. Although it is painful since it is NOT reliable:
void RayCastHandler::triggerTest( ... )
{
...
// 1 millisecond delay time
QTimer::singleShot(1, [rayCaster, origin, direction, length](){rayCaster->trigger(origin, direction, length);});
...
}
However, if I use no delay time, at some point, the ray caster stops unexpectedly, without sending any signal containing hit results, and ray caster stays enabled forever. Looks like ray-caster gets stuck:
void RayCastHandler::triggerTest( ... )
{
...
// No delay
rayCaster->trigger(origin, direction, length);
...
}
I've got this stream which shows/hides notifications:
this.subscription = this.notificationsApi.notifications$.pipe(
concatMap((event) => {
return of(event).pipe(
delay(450),
tap(() => {
this.notification = event;
this.isActive = true;
this.cd.markForCheck();
}),
delay(isDefined(event.showFor) ? event.showFor : this.hideAfter),
/// Pause here if you hover over the notification ///
tap(() => {
this.isActive = false;
this.cd.markForCheck();
}),
delay(450)
);
})
).subscribe(() => {});
What I would like to do is pause the stream when you hover over the notification and continue when you're no longer hovering over it:
<div (mouseover)="pause()" (mouseout)="continue()"></div>
This is where I can't seem to find a solution that works in this case. I'm assuming I have to use another 1-2 Subjects and then use switchMap depending on if you pause or continue but like I said I can't figure out how exactly.
I tried looking at this StackBlitz for switchMap pause/resume functionality but when I tried that approach it didn't show any notifications at all.
Any pointers?
Check this stackblitz interactive and this static viz example
The main trick was to wait at least for
notification show delay
and the next message on the stream
and let mouse ins and outs to add to the delay.
The magic inside the concatMap does that (at least, I think it does...)
To start, we take the notifications$ and concatMap a delay on it. Therefore each msg would be shown at least DELAY time
NOTE: pseudocode
notifications$.concatMap(msg =>
timer(DELAY)
.ignoreElements()
.startWith(msg)
)
Then we want the mouse to delay the delay
notifications$
.concatMap(msg =>
mouse$
.switchMap(isOver => { // < We re-delay on mouse state change
if (isOver) {
return empty() // < Do nothing when user hovers
}
return timer(DELAY); // < after DELAY -- take in next msgs
})
// we need only one completion event from this mouse$+ stream
.take(1)
// existing logic to turn delay stream into msg stream with delay
.ignoreElements()
.startWith(msg)
)
Finally, if next message comes after the DELAY -- we need to still listen to mouse hovers and delay by them
// store current msg index
let currentMsgIndex = -1;
notifications$
// store current msg index
.map((msg,i) => {
currentMsgIndex = i;
return msg;
})
.concatMap((msg, i) => {
// we listen to events from the mouse
return memMouse$
// if mouse pos changed -- reeval timeout
.switchMap(value => {
// do nothing on mouse in
if (value) {
return empty();
}
// until next msg comes in -- we're tracking mouse in/out
let nextMsgAwait$;
if (i == currentMsgIndex) {
// current msg is latest
nextMsgAwait$ = notifications$.pipe(take(1));
} else {
// we already have next msgs to show
nextMsgAwait$ = of(void 0);
}
// if mouse is away -- wait for
// - timer for TIMEOUT
// - and till new msg arrives
// until then -- user can mouse in/out
// to delay the next msg display
return forkJoin(
timer(TIMEOUT)
, nextMsgAwait$
);
}),
// we need only one completion event from this mouse$+ stream
.take(1)
// existing logic to turn delay stream into msg stream with delay
.ignoreElements()
.startWith(msg)
})
For better understanding please see above mentioned examples -- I've added some comments there.
I'm trying to mimic SFML's PollEvent(Event &event) function in Windows. It seems far more complicated that I imagined. Note that I already encapsulated the window procedure function in my class.
There could be many "window events" in my program - WindowMoved, WindowResized etc.
My first attempt was to have a private data member in the class, defined as WindowEvent *_lastWindowEvent. This variable will be set if PeekMessage() returns a non-zero value, just before DispatchMessage() is called. Then, winProc() will edit _lastWindowEvent, depending on the message it will receive.
The drawback here is that I noticed that winProc() may be called with a MSG parameter regardless of DispatchMessage(), like with the WM_SETCURSOR message.
Then I thought about having instead a std::queue<WindowEvent> in my class, when winProc() continuously pushes WindowEvents to it. The problem here is that sometimes the window procedure function keeps getting messages and won't return. This happens when I drag-move the window (then the WM_MOVING message is continuously called, along with other messages). The code after DispatchMessage() will not run until I release my mouse. This also happens when resizing the window.
Did I grasp anything wrong? How do you think such PollEvent function can be implemented?
Given that PollEvent is primarily for a game loop style design, you can probably poll for what you need while simultaneously servicing the Windows event loop:
class Window
{
HWND _hwnd; // Win32 handle to the window
RECT _lastWindowSize; // last known window size
POINT _lastMousePos; // last known mouse position on window
BYTE _lastKeyboardState[256]; // last known key state
std::list<Event> _events; // unprocessed events
public:
bool PollEvent(Event* pEvent);
};
bool Window::PollEvent(Event* pEvent)
{
// return any previously queued events
if (_events.size() > 0)
{
*pEvent = _events.pop_front();
return true;
}
// process 1 windows event message
if (PeekMessage(&msg, _hWnd, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
if (msg.msg == WM_QUIT)
{
*pEvent = EXIT_EVENT; // special handling for WM_QUIT
return true;
}
}
// -----------------------------------------
// poll keyboard state
BYTE kbState[256];
GetKeyboardState(kbState);
bool isKeyboardEvent = false;
if (memcmp(_lastKeyboardState, kbState, 256) != 0)
{
// not shown
// compute diff of kbState and _lastKeyboardState
// generate a keyboard event and add to the queue
Event kbevt;
kbevt.type = KeyEvent;
kbevt.code = <computed code based on diff above>
_events.push_back(kbevt);
}
memcpy(_lastKeyboardState, kbState, 256);
// -----------------------------------------
// -----------------------------------------
// poll window size changes
RECT rectWindowSize;
int width, height, oldwidth, oldheight;
GetClientRect(&rectWindowSize);
width = rectWindowSize.right - rectWindowSize.left;
height = rectWindowSize.bottom - rectWindowSize.top;
oldwidth = _lastWindowSize.right - _lastWindowSize.left;
oldheight = _lastWindowSize.bottom - _lastWindowSize.top;
if ((width != oldwidth) || (height != oldheight))
{
Event sizeEvent;
sizeEvent.type = SizeEvent;
sizeEvent.width = width;
sizeEvent.height = height;
_events.push_back(kbevt);
}
_lastWindowSize = rectWindowSize;
// -----------------------------------------
// not shown - computing mouse position, joystick position, text stuff
// if at least one event was queued - return it now
if (_events.size() > 0)
{
*pEvent = _events.pop_front();
return true;
}
return false;
}
In my Mac application I am trying to intercept right mouse down/up events using CG Event Taps. I have the code that is registering as a listener working just fine. What I am trying to do is intercept when the user clicks down with the right mouse button, and eat the event temporarily. When they let go of the right mouse button I want to post a right mouse down event if they haven't moved the mouse since the original mouse down event. If they have moved the mouse I want my app's code to do something different. This all works great if I run the code on my Macbook using the trackpad. However, when I plug a mouse into the same computer every other mouse down event does not trigger my callback.
The basic logic for doing this is I keep track of an "ignore next event" bool. When my program first runs this is set to false. When I get a right mouse down event I return NULL. When the right mouse up event triggers I create and post a new right mouse down event with ignoreNext to true. I then return the right mouse up event.
Here is my code:
CGPoint mouseDownPoint;
bool ignoreNext;
//---------------------------------------------------------------------------
CGEventRef MouseTapCallback( CGEventTapProxy aProxy, CGEventType aType, CGEventRef aEvent, void* aRefcon )
//---------------------------------------------------------------------------
{
if( aType == kCGEventRightMouseDown ) NSLog( #"down" );
else if( aType == kCGEventRightMouseUp ) NSLog( #"up" );
else NSLog( #"other" );
NSLog( #"ignored: %d", ignoreNext );
CGPoint theLocation = CGEventGetLocation(aEvent);
if( !ignoreNext )
{
if( aType == kCGEventRightMouseDown )
{
mouseDownPoint = theLocation;
return NULL;
}
else if( aType == kCGEventRightMouseUp )
{
if( abs( theLocation.x - mouseDownPoint.x ) < 1 &&
abs( theLocation.y - mouseDownPoint.y ) < 1 )
{
ignoreNext = true;
CGEventRef theNewEvent = CGEventCreateMouseEvent( NULL,
kCGEventRightMouseDown,
mouseDownPoint,
kCGMouseButtonRight );
CGEventSetType( theNewEvent, kCGEventRightMouseDown );
CGEventPost( kCGHIDEventTap, theNewEvent );
return aEvent;
}
else
{
// execute my app's code here...
return NULL;
}
}
}
ignoreNext = false;
return aEvent;
}
The output for this when I test it with the track pad is (working correctly):
down
ignored: 0
up
ignored: 0
down
ignored: 1
The output for this when I test it with an actual mouse (note: the mouse down event is missing on the second run through):
First time clicking down then up...
down
ignored: 0
up
ignored: 0
down
ignored: 1
Second time, the mouse down event doesn't trigger my callback...
up
ignored: 0
Has anyone seen anything like this before, and if so, what did you do to solve this problem? Thanks for your time.