Support Board
Date/Time: Fri, 29 Nov 2024 00:03:15 +0000
[Programming Help] - canceled stop order continues to have status SCT_OSC_OPEN
View Count: 934
[2023-02-17 15:09:35] |
Berliner JFK - Posts: 45 |
I have an automated trading system that uses stop orders regularly, and so is constantly creating them and canceling them. For error checking purposes, my code always remembers the last created and canceled stop order ID's and compares them with the open / canceled stop orders ID's from the Sierra Chart trade orders list: // code queries trade orders list to find the last open stop order
while(sc.GetOrderByIndex(StopIndex, StopOrderData) != SCTRADING_ORDER_ERROR) { StopIndex = StopIndex + 1; int StopOrderStatusCode = StopOrderData.OrderStatusCode; int StopOrderTypeAsInt = StopOrderData.OrderTypeAsInt; if ((StopOrderStatusCode == SCT_OSC_OPEN) && (StopOrderTypeAsInt == 2)) StopInternalOrderID = StopOrderData.InternalOrderID; } // code queries trade orders list to find the last canceled stop order ID
while(sc.GetOrderByIndex(CancelIndex, CancelOrderData) != SCTRADING_ORDER_ERROR) { CancelIndex = CancelIndex + 1; int CancelOrderStatusCode = CancelOrderData.OrderStatusCode; int CancelOrderTypeAsInt = CancelOrderData.OrderTypeAsInt; if ((CancelOrderStatusCode == SCT_OSC_CANCELED) && (CancelOrderTypeAsInt == 2)) CancelInternalOrderID = CancelOrderData.InternalOrderID; } What's happening is that my system finds the same stop order ID both as "SCT_OSC_OPEN" and "SCT_OSC_CANCELED" and reports a mismatch. When I catch the error and look in the trade orders window, the stop order always shows "Canceled". The trade activity log also shows that the stop order was properly canceled, seconds after the cancel order was placed. Therefore I can detect no reason why the code finds it with the status "SCT_OSC_OPEN". Can you please tell me why this is happening? FWIW this is simulated trading. Thanks! Date Time Of Last Edit: 2023-02-17 16:41:52
|
[2023-02-18 00:22:41] |
Berliner JFK - Posts: 45 |
I found a potential clue today. If a disconnect / reconnect is performed between trades, this seems to solve the problem. Why, I don't know, but maybe this is helps to understand what the root cause is. Thanks again! |
[2023-02-19 13:22:10] |
Berliner JFK - Posts: 45 |
Based on the fact the a disconnect / reconnect solves this problem, and what I found in the documentation this appears to be a housekeeping issue with Sierra Chart. I'm guessing the order is showing up twice, still as SCT_OSC_OPEN and after canceling as SCT_OSC_CANCELED. Because I'd like to to avoid a programmatic disconnect / reconnect I found this possibility: sc.RefreshTradeData(). Here is the text in the documentation: Normally there is never a reason to use this function. It is generally never recommended to make a call to this function.
This seems to be the perfect function to correct this problem, but it seems like you recommend not to use it. Will calling this function cause problems in live trading? Thanks! Date Time Of Last Edit: 2023-02-19 13:24:30
|
[2023-02-19 17:31:41] |
Sierra_Chart Engineering - Posts: 17213 |
What do you mean by this: What's happening is that my system finds the same stop order ID both as "SCT_OSC_OPEN" and "SCT_OSC_CANCELED" An order can have a different Status at different points in time. That is perfectly normal and expected. We really do not understand at all the problem that you are having. What is the problem to begin with?: I found a potential clue today. If a disconnect / reconnect is performed between trades, this seems to solve the problem.
During a continuous iteration of orders, done correctly, during one custom study function call, your custom study is not going to be encountering the same Internal Order ID more than once. Sierra Chart Support - Engineering Level Your definitive source for support. Other responses are from users. Try to keep your questions brief and to the point. Be aware of support policy: https://www.sierrachart.com/index.php?l=PostingInformation.php#GeneralInformation For the most reliable, advanced, and zero cost futures order routing, use the Teton service: Sierra Chart Teton Futures Order Routing Date Time Of Last Edit: 2023-02-19 17:35:04
|
[2023-02-19 18:34:01] |
Berliner JFK - Posts: 45 |
I will do my best to explain. Here is what the ACSIL code does: 1. first a stop order is placed 2. at some later time the stop order is canceled 3. right after canceling the stop order, the code searches the trade order list (see code in first post) using the criteria "SCT_OSC_CANCELED" in order to confirm that the stop order is in fact canceled. This is a double-check and the code always finds the order ID that was just canceled. This is the expected behavior and is not the problem. 4. right after searching the trade order list for the canceled order, the code also searches it for any open stop orders using the criteria "SCT_OSC_OPEN". This is a double-check to ensure that any open stop orders still match the stop orders that the code expects are still open. Here is where the problem happens. When the trade order list is searched for open orders using the criteria "SCT_OSC_OPEN", it finds the order that was just canceled. That is, the order that was just canceled can be found using both the criteria "SCT_OSC_CANCELED" and "SCT_OSC_OPEN", meaning that it is in the trade order list twice, once as canceled (expected) once as open (not expected). I found a potential clue today. If a disconnect / reconnect is performed between trades, this seems to solve the problem.
If a programmatic disconnect / reconnect (sc.ReconnectToExternalServiceServer = true) is performed right after canceling the stop order, but before searching the trade order list, the canceled stop order no long shows up as "SCT_OSC_OPEN", rather only once as "SCT_OSC_CANCELED" as expected. I hope that helps. Thanks! |
[2023-02-19 19:27:59] |
Sierra_Chart Engineering - Posts: 17213 |
If an ACSIL study cancels an order, and immediately during the same function call you are checking to see if it is canceled, you should find it canceled in the case of Trade Simulation Mode but you will not find it canceled in the case of non-simulated trading. Something to be aware of. More information: Automated Trading Management: Differences Between Live Automated Trading and Simulated Automated Trading When the trade order list is searched for open orders using the criteria "SCT_OSC_OPEN", it finds the order that was just canceled. That is, the order that was just canceled can be found using both the criteria "SCT_OSC_CANCELED" and "SCT_OSC_OPEN", meaning that it is in the trade order list twice, once as canceled (expected) once as open (not expected). Something is definitely wrong with your code. Check your code. This is not possible at all.
Sierra Chart Support - Engineering Level Your definitive source for support. Other responses are from users. Try to keep your questions brief and to the point. Be aware of support policy: https://www.sierrachart.com/index.php?l=PostingInformation.php#GeneralInformation For the most reliable, advanced, and zero cost futures order routing, use the Teton service: Sierra Chart Teton Futures Order Routing Date Time Of Last Edit: 2023-02-19 19:30:49
|
[2023-03-09 13:28:44] |
Berliner JFK - Posts: 45 |
I believe I've solved this problem, but have a question. If a variable is not explicitly persistent, can it still have characteristics of a persistent variable? The variables I was using to store the stop ID information, despite not being explicitly defined as persistent, would still retain their values for hours. This was not expected behavior (why have persistent variables, if normal variables are already persistent?). The solution was to zero these after each loop, and also explains why a reconnect / reload solved the problem. Can variables not explicitly defined as persistent actually be persistent? Is there a rule for that, when they will be reset / erased v. when they will be persistent and retain their values and for how long? Thanks! Date Time Of Last Edit: 2023-03-09 13:42:28
|
[2023-03-09 16:27:03] |
ondafringe - Posts: 286 |
From what I understand: If a variable remains in scope, it will retain its value until explicitly changed. I believe that is standard within the realm of programming.
|
[2023-03-09 17:00:08] |
Berliner JFK - Posts: 45 |
Hi, thanks for your answer. What does "remain in scope" mean? I'm new to programming, like you can see. My script has sc.AutoLoop = 1 and sc.UpdateAlways = 1, and I understand that by nature looping means that variables will not be persistent. If this were not the case, there wouldn't be variables specifically designed to be persistent I assume. Whether this means that they zero each loop or are "lost" or just can't be counted up to retain their value, I'd like to understand and also under what conditions which is true. Thank you again for your answer, much appreciated! |
[2023-03-09 18:03:41] |
ondafringe - Posts: 286 |
Let's see if I can explain this in language that can be understood. :) Consider this code: if (whatever) { int test = 10; //"test" variable was created here, and is said to be "in scope" } //"test" variable goes out of scope and no longer exists The variable "test" was created within the if-construct and is only alive and readable within that construct. Once execution leaves that construct, the "test" variable is automatically destroyed. So within that construct, the variable is said to be "in scope." ================ Now consider this code: int test = 0; //"test" variable was created here and is said to be "in scope" for this construct and any sub-constructs contained within the broader construct if (whatever) { test = 10; //test variable is still in scope and can be read here } //test variable is still in scope, still readable, and will retain its value until explicitly changed or until, it goes out of scope The "test" variable was created outside of the if-construct, so it now has a broader scope and can be read within that broader scope and also within any sub-scope, such as the if-construct, as long as the sub-construct is contained within the broader construct. ============ Now consider this code: if (whatever) { int test = 0; //"test" variable was created within the first if-construct, and is said to be "in scope" for that and any sub-constructs contained within the first if-construct. if (whateverelse) { test = 10; //test variable is still in scope and can be read here } //test variable is still in scope and can be read here } //test variable goes out of scope and no longer exists And on and on it goes, where it ends, only the programmer knows. Hopefully, I got all that right. :) Date Time Of Last Edit: 2023-03-09 18:16:40
|
[2023-03-09 18:45:32] |
Berliner JFK - Posts: 45 |
Hello @ondafringe, appreciate your excellent explanation! Based on your example, here is how I coded my variable: int test;
if (whatever) { test = 10; } That means that it remains in scope after the if-then construct, and can be read in the broader scope if I understand you right. So, if I were to rewrite my code as below, the variable would be "destroyed" outside of scope? if (whatever) { int test = 10; } That is actually what I want, because right now the variable value persists (even through thousands of loops) even though I want it to be "destroyed" after each loop. Thanks again! |
[2023-03-09 19:09:19] |
ondafringe - Posts: 286 |
In your first example, your variable would remain in-scope as long as that scope is the highest level scope. The fact that your variable is retaining its value suggests your variable is remaining in-scope. In your second example, yes, once execution leaves that scope, that if-construct, your variable will no longer exist. But... your variable will be recreated and destroyed every single time code execution passes through that if-construct. Date Time Of Last Edit: 2023-03-09 19:11:39
|
[2023-03-09 19:15:45] |
Berliner JFK - Posts: 45 |
Thanks for taking the time to explain, @ondafringe!
|
[2023-03-16 15:07:04] |
Berliner JFK - Posts: 45 |
Hello @ondafringe. It took some time to understand what you wrote, and reflect on how it related to my code. In short, you were right. This was my issue. I was using a non-persistent variable, but it was in scope and therefore retained it's value regardless of how many loops or how long the program ran. Unless the code returned to that scope (e.g. inside an if-then statement), the variable retained it's value. To me, as a new programmer, it was very difficult to get my head around this concept, but it explains why a non-persistent variable acted like a persistent variable, instead of being "destroyed" after the function returns / loops. For now, I solved the problem by explicitly resetting the variable to zero, but I suppose I could have also solved it by moving the variable out of scope, i.e. declaring it at the base level of my script, correct? Either way, thank you. I can finally appreciate everything that you wrote, and it did help me. Date Time Of Last Edit: 2023-03-16 15:18:28
|
[2023-03-16 20:43:04] |
ondafringe - Posts: 286 |
I suppose I could have also solved it by moving the variable out of scope, i.e. declaring it at the base level of my script, correct?
In Post #11, above, I thought that's what you were going to do. IMO, it's best to declare variables with the narrowest scope possible, scope to be determined by how/where/when you need to access that particular variable. |
[2023-03-16 22:06:25] |
Berliner JFK - Posts: 45 |
Thank you, @ondafringe. Here is the code before: // BASE LEVEL
int Index = 0; // THIS IS THE PROBLEM VARIABLE (StopOrderID) int StopOrderID; s_SCTradeOrder Data; // SCAN FOR OPEN STOP ORDERS while(sc.GetOrderByIndex(Index, Data) != SCTRADING_ORDER_ERROR) { // IN SCOPE Index = Index + 1; int StatusCode = Data.OrderStatusCode; int TypeAsInt = Data.OrderTypeAsInt; if ((StatusCode == SCT_OSC_OPEN) && (TypeAsInt == 3)) // SAVE OPEN STOP ORDER ID AS StopOrderID StopOrderID = Data.InternalOrderID; } Here is the code after: // BASE LEVEL
int Index = 0; // ***ONLY CHANGE IS EXPLICIT DEFINIION "= 0", PROBLEM SOLVED*** int StopOrderID = 0; s_SCTradeOrder Data; // SCAN FOR OPEN STOP ORDERS while(sc.GetOrderByIndex(Index, Data) != SCTRADING_ORDER_ERROR) { // IN SCOPE Index = Index + 1; int StatusCode = Data.OrderStatusCode; int TypeAsInt = Data.OrderTypeAsInt; if ((StatusCode == SCT_OSC_OPEN) && (TypeAsInt == 3)) // SAVE OPEN STOP ORDER ID AS StopOrderID StopOrderID = Data.InternalOrderID; } The variable StopOrderID was declared at the base level (int StopOrderID;), but not defined (int StopOrderID = 0;). I thought that by declaring it at the base level, it would be "destroyed", but only the explicit definition worked. That's all I know, and the solution works. I imagine the question is "Why did the simple declaration (int StopOrderID;) at the base level not "destroy" the variable, instead requiring an explicit definition (int StopOrderID = 0;)? Date Time Of Last Edit: 2023-03-16 22:08:59
|
[2023-03-16 23:03:27] |
ondafringe - Posts: 286 |
A few things to consider: 1. Whenever you declare a variable, you should always initialize it (set it to some default value), which you did in your second code snippet. 2. stopOrderID is in scope for the entirety of your code snippet. It will not be destroyed unless it goes out of scope (maybe in some other part of your code). Revisit the examples in Post #10, above. 3. Your if-statement is incomplete, which *may* be part of your earlier problem. If you *only* want this line (StopOrderID = Data.InternalOrderID) to execute based on the if-statement condition being true, then you need to complete the if-statement, as so: if ((StatusCode == SCT_OSC_OPEN) && (TypeAsInt == 3)) { StopOrderID = Data.InternalOrderID; } Unless I'm missing something, based on your code, your if-statement condition is being ignored, so stopOrderID is being updated on every pass, and will retain its value unless it goes out of scope, or is explicitly reset. And you are explicitly resetting it to zero in your second code snippet; or, more accurately, you are redeclaring the variable and giving it a default value of zero. Edit: After rereading your last post, I wasn't certain what you meant by "base level." I now think you are referring to the main part of the study where your primary code is encompassed within: SCSFExport scsf_XXXXXXXXXX(SCStudyInterfaceRef sc) { } If that is the case, then from what I *think* I know is, variables declared within that structure are destroyed after leaving the end of that structure, and then recreated upon being redeclared once the declaration code is re-executed on subsequent passes through that structure. Having said that, if you try to access that variable prior to redeclaration, I'm guessing you will probably see garbage (or something akin to garbage) because that variable would no longer exist until it's been redeclared. So your StopOrderID *should* be destroyed as it goes out of scope, and then gets recreated/destroyed again and again upon subsequent passes, which is what's happening... because if it wasn't destroyed, redeclaring a local variable that is still in scope would probably throw a compile error, which apparently didn't happen. And declaring StopOrderID without initializing it, as you first did, would probably result in StopOrderID containing garbage (or something akin to garbage) until it had been assigned a value. Now, I'm no code guru, not even close, but that's my take. Date Time Of Last Edit: 2023-03-17 05:12:45
|
[2023-03-17 05:11:35] |
Sierra_Chart Engineering - Posts: 17213 |
Our only comment on this is that this is a C++ programming question. Make reference to C++ programming reference information: Can variables not explicitly defined as persistent actually be persistent? Is there a rule for that, when they will be reset / erased v. when they will be persistent and retain their values and for how long? This is not Sierra Chart specific in any way and we have no way to answer your question without seeing the code and understanding it and this is in the realm of programming help which we do not provide. But in general unless the variable is global or static, which we do not recommend using, it is not persistent across function calls at all. Sierra Chart Support - Engineering Level Your definitive source for support. Other responses are from users. Try to keep your questions brief and to the point. Be aware of support policy: https://www.sierrachart.com/index.php?l=PostingInformation.php#GeneralInformation For the most reliable, advanced, and zero cost futures order routing, use the Teton service: Sierra Chart Teton Futures Order Routing Date Time Of Last Edit: 2023-03-17 05:12:14
|
[2023-03-17 11:58:09] |
Berliner JFK - Posts: 45 |
Thank you @ondafringe, @Tony and @Sierra Chart Engineering. Here is what I know: 1. when I set the stop order variable explicitly to zero the problem is solved (see post # 15 above) 2. over a month of testing Sierra Chart's Simulation Mode(=on), Simulated Trading Service and Live Trading(Teton) I could not find evidence of a stop order housekeeping issue 3. over a day of testing persistence of standard variables in Sierra Chart/C++ with sample code, I could not recreate this issue. It only occurs in the context of my study function / trading system, which is automated and runs 100% unattended. This issue was solved by the explicit definition of the stop order variable (BEFORE: int stoporderID; AFTER: int stoporderID = 0;). Also, performing a manual refresh/recalculate (Insert) when it occurs, fixes it as well. I believe that this has to do with a special case of persistence possible in C++ @ondafringe. For now, I'm considering this solved, but hope that the root cause will become clear in the future. Thanks again @ondafringe, @Tony and @Sierra Chart Engineering! EDIT: I may do a deep-dive one day and add a ton of debug code to root cause this issue, because I'm not really satisfied with any of the explanations, but it's not a priority now. Date Time Of Last Edit: 2023-03-17 16:25:38
|
To post a message in this thread, you need to log in with your Sierra Chart account: