FTX CCXT cancel SL / TP after position closes - ccxt

I already have the code to send orders to FTX (with TP and SL).
But since TP and SL are not 'attached' to the position and the positions are aggregated it makes a mess with orders.
I have seen people suggest cancelling all orders before opening a new one: https://stackoverflow.com/a/69371405/6014804
Which is a nice idea but unusable in my case.
I regularly have several current positions at the same time.
So I can't cancel all pending orders as soon as I open a new position. Because some orders are still active and relevant.
The only option I guess is to fetch closed orders/positions (when a TP / SL is hit) to individually cancel the remaining order to this position (the opposite order, either TP / SL). Right?
Even if it's the right solution, I don't know how to do that.
Has anyone ever experienced that? Thanks in advance.

I'm citing the solution CCXT team has come up with, on their dedicated GitHub issues platform: https://github.com/ccxt/ccxt/issues/15214
place tp order
place sl order
start a polling mechanism to detect when one or another order is
closed
after detecting, cancel the remaining
Very rough example:
tp_order = await exchange.create_order(...)
sl_order = await exchange.create_order(...)
while True:
if tp_status == 'open' and sl_status == 'closed':
# cancel tp order
cancel_tp_order = await exchange.cancel_order(tp_order['id'])
break
if sl_status == 'open' and tp_status == 'closed':
# cancel sl order
cancel_sl_order = await exchange.cancel_order(sl_order['id'])
break
asyncio.sleep(5) # sleep 5 seconds before trying again
Alternatively, you could use WS (they're free now) to detect in real-time which order was filled and immediately close the other.

Related

How can I observe an other apps launch?

For a mental health app project, I need to intercept the startup of specific apps (like Instagram) and check if they used instagram the n-th time, possibly opening a questionair etc.
Searching for a solutions online, I came across the "android.app.usage" API. I could not get my around how to use this.
Do I need a for every running background service which does active polling with the usage api?
Or is their a way to say "run this code or start this app/service when appXY launches"?
Looking forward to any kind of input :)
Greetings Pascal
You can't listen out for an "app is being opened" intent unfortunately, Android doesn't support it. Your approach is likely the best workaround, to state it explicitly:
Have a foreground service running (so it is less likely to be killed by the OS) at all times.
Check regularly the currently running app, and see if it's the one you're trying to look for.
If this is different to last time you checked, do whatever you need to. Perhaps this will include keeping track of last time the app was opened, how many times it's been opened etc.
As a warning however, the OS won't really like this, and there's likely to be an impact on battery life. Whatever you do, make sure this check isn't happening when the screen is off, happening as infrequently as possible, and doesn't include any unnecessary computation, otherwise the user will quickly notice the negative impact.
Here's an extract from an article that looks like it'll be able to fetch the latest app even on later versions:
var foregroundAppPackageName : String? = null
val currentTime = System.currentTimeMillis()
// The `queryEvents` method takes in the `beginTime` and `endTime` to retrieve the usage events.
// In our case, beginTime = currentTime - 10 minutes ( 1000 * 60 * 10 milliseconds )
// and endTime = currentTime
val usageEvents = usageStatsManager.queryEvents( currentTime - (1000*60*10) , currentTime )
val usageEvent = UsageEvents.Event()
while ( usageEvents.hasNextEvent() ) {
usageEvents.getNextEvent( usageEvent )
Log.e( "APP" , "${usageEvent.packageName} ${usageEvent.timeStamp}" )
}

PsychoPy: make trials happen with keypress until routine ends at time x

I have a routine with multiple possible trials (in a loop), and the participant must press a key to go to the next trial. I want these trials to go on (with keypresses) until a certain time has passed of the routine, say 5 seconds, regardless of how many possible trials are left in my conditionsFile. At the 5-second mark, the routine should end.
(If this is relevant: each trial is only displayed once.)
I've tried a few things, all of which only end up making the routine skip to the next trial after 5 seconds, but still going through all the possible trials, i.e. not ending the routine at 5 s.
For example, I've tried adding:
# ------Prepare to start Routine "Images"-------
continueRoutine = True
routineTimer.add(5)
and then
# -------Run Routine "Images"-------
while continueRoutine and routineTimer.getTime() > 0:
I've also tried adding this to the while sequence from above:
if image.status == STARTED:
# is it time to stop? (based on global clock, using actual start)
if tThisFlipGlobal > image.tStartRefresh + 5.0-frameTolerance:
# keep track of stop time/frame for later
image.tStop = t # not accounting for scr refresh
image.frameNStop = frameN # exact frame index
win.timeOnFlip(image, 'tStopRefresh') # time at next scr refresh
image.setAutoDraw(False)
Can anyone help?

GML Alarm event not working second time

I have my game setup so that it starts and goes back to a loading screen room for 45 steps after which the next room is randomized. So at alarm[0] the following code activates:
randomize();
chosenRoom = choose(rm_roomOne, rm_roomTwo, rm_roomThree, rm_roomFour);
room_goto(chosenRoom);
The code here works fine the first time, but when it goes back from the randomly chosen room to the loading screen room it stays there and doesn't execute the code again.
Any help would be very much appreciated.
This may sound stupid but did you remember to set the alarm again after it's gone off? I know I've done this several times without thinking. Without seeing your code, I assume that after the alarm goes off it's not being set again, so it won't go off again.
I'm guessing the control object is "persistant", thus the Control Object only exists once and will remain forever (also after swithcing rooms) - thus thie create event only gets fired once - thus the alarm only gets set once.
Try to move your code to the event "Room Start" in your controller and it will work.
you can use event_perform(ev_alarm,0);.
The code here performs alarm[0] after 45 steps. after 45 steps again it triggers alarm[0]. Note that you have to put it in step event. And you have to initialize wait variable and times to zero in create event.
times is the repeat and wait is distance between events.
if(wait == 45 && times !=2){
event_perform(ev_alarm,0);
times++;
wait = 0;
}
else{
wait++;
}

multi threading - add more threads and continue the operation

ok here is my code :
For i = 0 To 10
Dim tTemp As Threading.Thread = New Threading.Thread(AddressOf dwnld)
tTemp.IsBackground = True
'tTemp.Start(geturl)
lThreads.Add(tTemp)
'MsgBox(lThreads.Item(i).ThreadState)
Next
I create a list of threads with 10 threads, assign them a function, properties and add them to the list.
'While ListBox2.Items.Count > 0
For i = 0 To lThreads.Count - 1
If (lThreads.Item(i).ThreadState = 12) Then
If (ListBox2.Items.Count > 0) Then
lThreads.Item(i).Start(geturl)
If (i = lThreads.Count - 1) Then
i = 0
End If
Else
Exit For
End If
'MsgBox(lThreads.Item(i).ThreadState)
ElseIf (lThreads.Item(i).ThreadState = 16) Then
lThreads.RemoveAt(i)
Dim tTemp As Threading.Thread = New Threading.Thread(AddressOf dwnld)
tTemp.IsBackground = True
lThreads.Add(tTemp)
If (i = lThreads.Count - 1) Then
i = 0
End If
End If
Next
What's happening is, i see the threads stop after the function dwnld is completed. So i first check for the state (12 means background and unstarted). On case 12 start the thread and in case 16 (stopped) remove that particular thread and add a different thread like i add 10 above.
Also there is a check when the i counter reaches last number, restart the whole loop by assigning i=0.
The program downloads some web pages, the url is passed from the listbox2. The geturl will pass the url and remove it from the list. So when the listbox is empty, exit the for loop.
But the above code is running for only 11 times and it does not restart. I tried using a lable and goto but it simple hangs.
Can anyone tell me what to do?
What i want is to maintain 10 threads to keep downloading the web pages and when the list is empty, exit the function.
Trying to manually manage your own custom pool of threads is probably the wrong approach here. Use ThreadPool.QueueUserWorkItem or preferrably the new Task class. The thread pooling is managed for you which greatly simplifies the code. Completely scrap this code and start over using one of the techniques I just mentioned. If you run into problems implementing either of these techniques then post a more specific question.
Micro-management of threads is, well, just a really bad idea. The moment I see anyone trying to maintain a list of threads that are continually created, terminated and destroyed I just know they are doomed. I have seen experienced professionals trying to do it - it's fun looking on, waiting for the inevitable spectacular failure after months of trying to fix the unfixable.
Thread pools are, typically, nothing of the sort. They are usually a pool of tasks - task class instances on a producer-consumer queue - that several threads feed off as and when they are free to do work. The work threads auto-manage themselves by getting new tasks themselves when they have finished with the old one - no need for any higher-level micro management.
Listen to #Brian - forget managing lists of threads, checking their state and all that gunge. It'll just make you ill. Go with ThreadPool.QUWI or Tasks.

Doing an atomic update of the first instance in a QuerySet

I'm working on a system which has to handle a number of race-conditions when serving jobs to a number of worker-machines.
The clients would query the system for jobs with status='0' (ToDo), then, in an atomic way, update the 'oldest' row with status='1' (Locked) and retrieve the id for that row (for updating the job with worker information like which machine is working on it etc.).
The main issue here is that there might be any number of clients updating at the same time. A solution would be to lock around 20 of the rows with status='0', update the oldest one and release all the locks again afterwards. I've been looking into the TransactionMiddleware but I don't see how this would prevent the case of the oldest one being updated from under me after I query it.
I've looked into the QuerySet.update() thing, and it looks promising, but in the case of two clients getting a hold of the same record, the status would simply updated, and we would have two workers working on the same job.. I'm really at a loss here.
I also found ticket #2705 which seems to handle the case nicely, but I have no idea how to get the code from there because of my limited SVN experience (the last updates are simply diffs, but I don't know how to merge that with the trunk of the code).
Code: Result = Job
class Result(models.Model):
"""
Result: completed- and pending runs
'ToDo': job hasn't been acquired by a client
'Locked': job has been acquired
'Paused'
"""
# relations
run = models.ForeignKey(Run)
input = models.ForeignKey(Input)
PROOF_CHOICES = (
(1, 'Maybe'),
(2, 'No'),
(3, 'Yes'),
(4, 'Killed'),
(5, 'Error'),
(6, 'NA'),
)
proof_status = models.IntegerField(
choices=PROOF_CHOICES,
default=6,
editable=False)
STATUS_CHOICES = (
(0, 'ToDo'),
(1, 'Locked'),
(2, 'Done'),
)
result_status = models.IntegerField(choices=STATUS_CHOICES, editable=False, default=0)
# != 'None' => status = 'Done'
proof_data = models.FileField(upload_to='results/',
null=True, blank=True)
# part of the proof_data
stderr = models.TextField(editable=False,
null=True, blank=True)
realtime = models.TimeField(editable=False,
null=True, blank=True)
usertime = models.TimeField(editable=False,
null=True, blank=True)
systemtime = models.TimeField(editable=False,
null=True, blank=True)
# updated when client sets status to locked
start_time = models.DateTimeField(editable=False)
worker = models.ForeignKey('Worker', related_name='solved',
null=True, blank=True)
To merge #2705 into your django, you need to download it first:
cd <django-dir>
wget http://code.djangoproject.com/attachment/ticket/2705/for_update_11366_cdestigter.diff?format=raw
then rewind svn to the necessary django version:
svn update -r11366
then apply it:
patch -p1 for_update_11366_cdestigter.diff
It will inform you which files were patched successfully and which were not. In the unlikely case of conflicts you can fix them manually looking at http://code.djangoproject.com/attachment/ticket/2705/for_update_11366_cdestigter.diff
To unapply the patch, just write
svn revert --recursive .
If your django is running on one machine, there is a much simpler way to do it... Excuse the pseudo-code as the details of your implementation aren't clear.
from threading import Lock
workers_lock = Lock()
def get_work(request):
workers_lock.acquire()
try:
# Imagine this method exists for brevity
work_item = WorkItem.get_oldest()
work_item.result_status = 1
work_item.save()
finally:
workers_lock.release()
return work_item
You have two choices off the top of my head. One is to lock rows immediately upon retrieval and only release the lock once the appropriate one has been marked as in use. The problem here is that no other client process can even look at the jobs which don't get selected. If you're always just automatically selecting the last one then it may be a brief enough of a window to be o.k. for you.
The other option would be to bring back the rows that are open at the time of the query, but to then check again whenever the client tries to grab a job to work with. When a client attempts to update a job to work on it a check would first be done to see if it's still available. If someone else has already grabbed it then a notification would be sent back to the client. This allows all of the clients to see all of the jobs as snapshots, but if they are constantly grabbing the latest one then you might have the clients constantly receiving notifications that a job is already in use. Maybe this is the race condition to which you're referring?
One way to get around that would be to return the jobs in specific groups to the clients so that they are not always getting the same lists. For example, break them down by geographic area or even just randomly. For example, each client could have an ID of 0 to 9. Take the mod of an ID on the jobs and send back those jobs with the same ending digit to the client. Don't limit it to just those jobs though, as you don't want there to be jobs that you can't reach. So for example if you had clients of 1, 2, and 3 and a job of 104 then no one would be able to get to it. So, once there aren't enough jobs with the correct ending digit jobs would start coming back with other digits just to fill the list. You might need to play around with the exact algorithm here, but hopefully this gives you an idea.
How you lock the rows in your database in order to update them and/or send back the notifications will largely depend on your RDBMS. In MS SQL Server you could wrap all of that work nicely in a stored procedure as long as user intervention isn't needed in the middle of it.
I hope this helps.