Support Board
Date/Time: Sat, 23 Nov 2024 15:07:03 +0000
[Programming Help] - ACSIL Custom Autotrading System assistance
View Count: 1813
[2024-08-07 13:44:35] |
User357489 - Posts: 72 |
Hi, ive been watching it and when i see the conditions as outlined above, it doesnt appear to be entering the trade what i am seeing however is increasing drawdown (which means it must be opening trades) however i dont think it is doing so in a manner in which i was trying to get across I cannot see the bracket orders when they are being openend, so to the naked eye, its opening and closing trades in drawdown, without displaying the bracket (which to me is an indication of the system working, you know) This led me to wonder- are the current entry conditions too "loose" hence the consistent drawdown (this doesnt bother me as its on sim account for testing, naturally- just stumped) Partly the reason why i wanted one of the entry conditions to check if the price level has a positive/negative delta at the same time that bid or ask pulling stacking values meet the threshold. Another condition i was planning to add was; the sum of the mbo orders on bid (5 depth levels in my case, as i have set market depth to 5) > ask sum, bolstering the directional bias of the conditions; yet became overwhelmed on how to do this :) EDIT: perhaps its becoming confused because the conditions can be met below/ above current price? in the example provided earlier, it was 73.64 that met the buy conditions while current price was 73.66. So my hopes were that conditions met, execute mkt order @ best price (in this case current price) Date Time Of Last Edit: 2024-08-07 13:46:55
|
[2024-08-07 13:49:09] |
User357489 - Posts: 72 |
as it has very consisitently drawdown, to a impressive degree (i added the successful build to several trade doms, different assets, and since has produced approx 800 trades, all losers bar 1! Which is incredible, never seen that occur in any novice program ive built so far! perhaps i should link it to another platform and reverse direction lol |
[2024-08-07 15:53:50] |
ForgivingComputers.com - Posts: 960 |
I cannot see the bracket orders when they are being openend, so to the naked eye, its opening and closing trades in drawdown, without displaying the bracket (which to me is an indication of the system working, you know)
The Trade Activity Log is your friend. In the [Trade Activity] tab, Use the Display menu to properly filter the results or you may see nothing. For each OCO Bracket, you will see three orders, their types, and prices. |
[2024-08-07 15:58:26] |
User357489 - Posts: 72 |
Hi there. I had it open alongside while I was running some tests however thanks for the suggestion, as I didn't actually know it showed that level of detail! So either something isn't quite correct in the execution logic, or my idea just sucks haha! Possibly the latter |
[2024-08-08 10:15:43] |
User357489 - Posts: 72 |
Good morning, to add to this; so i linked it to copy to an MT4 demo to try some stuff out- if i manually execute a market order, this copies across fine, so I've deduced something is not quite correct in the execution logic and/or it is immediately exiting upon detecting the relevant opposition conditions, it is not allowing the trade to run and only be filled by stop/ target orders. This was why i wanted to use the volume profile values displayed (set to ask volume- bid volume on the study), to differentiate buys from sells when the price level has VBP value >0/<0. code for reiteration: #include "sierrachart.h" , this build is successful but as mentioned above and in previous notes, i am biased towards it not functioning as intended. Hope this is clear, and hope my entry conditions were clear or at least you get the idea of what im trying to achieve :)
#include <unordered_map> #include <chrono> SCDLLName("Sweep Genie") struct TradeInfo { std::chrono::time_point<std::chrono::steady_clock> startTime; double startPrice; bool tradeEntered; int positionType; // 1 for buy, -1 for sell bool stopMovedToBreakeven; bool trailingStopActivated; int stopOrderID; }; std::unordered_map<int, TradeInfo> g_TradeInfo; void PlaceBracketOrder(SCStudyInterfaceRef& sc, TradeInfo& tradeInfo, int positionType, int orderQuantity, double price, int stopLossTicks, int takeProfitTicks) { s_SCNewOrder order; order.OrderType = SCT_ORDERTYPE_MARKET; order.OrderQuantity = orderQuantity; order.TimeInForce = SCT_TIF_GTC; // Define the attached orders order.Target1Offset = takeProfitTicks * sc.TickSize; order.Stop1Offset = stopLossTicks * sc.TickSize; // Set attached order types order.AttachedOrderTarget1Type = SCT_ORDERTYPE_LIMIT; order.AttachedOrderStop1Type = SCT_ORDERTYPE_STOP; int result = (positionType == 1) ? sc.BuyEntry(order) : sc.SellEntry(order); if (result > 0) { tradeInfo.startTime = std::chrono::steady_clock::now(); tradeInfo.startPrice = price; tradeInfo.tradeEntered = true; tradeInfo.positionType = positionType; tradeInfo.stopMovedToBreakeven = false; tradeInfo.trailingStopActivated = false; tradeInfo.stopOrderID = order.Stop1InternalOrderID; } } SCSFExport scsf_SweepGenie(SCStudyInterfaceRef sc) { if (sc.SetDefaults) { sc.GraphName = "Sweep Genie"; sc.AutoLoop = 0; sc.Input[0].Name = "Volume Threshold"; sc.Input[0].SetInt(1000); sc.Input[1].Name = "Order Quantity"; sc.Input[1].SetInt(1); sc.Input[2].Name = "Stop Loss Ticks"; sc.Input[2].SetInt(10); sc.Input[3].Name = "Take Profit Ticks"; sc.Input[3].SetInt(20); sc.Input[4].Name = "Trailing Stop Offset Ticks"; sc.Input[4].SetInt(5); sc.Input[5].Name = "VBP Study ID"; sc.Input[5].SetStudyID(0); // Default study ID, set by user. return; } int volumeThreshold = sc.Input[0].GetInt(); int orderQuantity = sc.Input[1].GetInt(); int stopLossTicks = sc.Input[2].GetInt(); int takeProfitTicks = sc.Input[3].GetInt(); int trailingStopOffsetTicks = sc.Input[4].GetInt(); int vbpStudyID = sc.Input[5].GetStudyID(); // Get the study ID for the VBP study SCDateTime currentTime = sc.CurrentSystemDateTime; auto& tradeInfo = g_TradeInfo[sc.ChartNumber]; s_SCPositionData positionData; sc.GetTradePosition(positionData); int currentPosition = positionData.PositionQuantity; bool buyConditionMet = false; bool sellConditionMet = false; double entryPrice = 0.0; // Iterate through the market depth levels to check pulling/stacking values for (int level = 0; level < 10; ++level) // Adjust 10 as necessary for the number of levels to check { s_MarketDepthEntry bidDepthEntry, askDepthEntry; double bidPullingStacking = 0.0, askPullingStacking = 0.0; if (sc.GetBidMarketDepthEntryAtLevel(bidDepthEntry, level)) { bidPullingStacking = sc.GetBidMarketDepthStackPullValueAtPrice(bidDepthEntry.Price); } if (sc.GetAskMarketDepthEntryAtLevel(askDepthEntry, level)) { askPullingStacking = sc.GetAskMarketDepthStackPullValueAtPrice(askDepthEntry.Price); } int profileIndex = 0; // Use 0 for the most recent profile s_VolumeAtPriceV2 volumeAtPrice; int PricesCount = sc.GetNumPriceLevelsForStudyProfile(vbpStudyID, profileIndex); for (int PriceIndex = 0; PriceIndex < PricesCount; ++PriceIndex) { if (sc.GetVolumeAtPriceDataForStudyProfile(vbpStudyID, profileIndex, PriceIndex, volumeAtPrice)) { // Buy condition: PullingStacking >= threshold and AskVolume - BidVolume > 0 if (volumeAtPrice.PriceInTicks == sc.PriceValueToTicks(bidDepthEntry.Price) && bidPullingStacking >= volumeThreshold && volumeAtPrice.AskVolume - volumeAtPrice.BidVolume > 0) { buyConditionMet = true; entryPrice = sc.Close[sc.ArraySize - 1]; // Set the entry price to the current price break; } // Sell condition: PullingStacking >= threshold and AskVolume - BidVolume < 0 if (volumeAtPrice.PriceInTicks == sc.PriceValueToTicks(askDepthEntry.Price) && askPullingStacking >= volumeThreshold && volumeAtPrice.AskVolume - volumeAtPrice.BidVolume < 0) { sellConditionMet = true; entryPrice = sc.Close[sc.ArraySize - 1]; // Set the entry price to the current price break; } } } if (buyConditionMet || sellConditionMet) { break; // Exit the loop if either condition is met } } // Execute Buy or Sell based on conditions if (buyConditionMet && currentPosition == 0) { PlaceBracketOrder(sc, tradeInfo, 1, orderQuantity, entryPrice, stopLossTicks, takeProfitTicks); } else if (sellConditionMet && currentPosition == 0) { PlaceBracketOrder(sc, tradeInfo, -1, orderQuantity, entryPrice, stopLossTicks, takeProfitTicks); } // Rest of the trade management logic if (tradeInfo.tradeEntered) { double stopLossPrice = tradeInfo.startPrice - (tradeInfo.positionType * stopLossTicks * sc.TickSize); double takeProfitPrice = tradeInfo.startPrice + (tradeInfo.positionType * takeProfitTicks * sc.TickSize); double trailingStopTriggerPrice = tradeInfo.startPrice + (tradeInfo.positionType * takeProfitTicks * 0.7 * sc.TickSize); if ((tradeInfo.positionType == 1 && (sc.Close[sc.ArraySize - 1] <= stopLossPrice || sc.Close[sc.ArraySize - 1] >= takeProfitPrice)) || (tradeInfo.positionType == -1 && (sc.Close[sc.ArraySize - 1] >= stopLossPrice || sc.Close[sc.ArraySize - 1] <= takeProfitPrice))) { sc.FlattenAndCancelAllOrders(); tradeInfo.tradeEntered = false; tradeInfo.positionType = 0; } else if (!tradeInfo.trailingStopActivated && tradeInfo.stopOrderID > 0 && ((tradeInfo.positionType == 1 && sc.Close[sc.ArraySize - 1] >= trailingStopTriggerPrice) || (tradeInfo.positionType == -1 && sc.Close[sc.ArraySize - 1] <= trailingStopTriggerPrice))) { tradeInfo.trailingStopActivated = true; s_SCNewOrder modifyOrder; modifyOrder.InternalOrderID = tradeInfo.stopOrderID; modifyOrder.Price1 = tradeInfo.startPrice + (tradeInfo.positionType * trailingStopOffsetTicks * sc.TickSize); int modifyResult = sc.ModifyOrder(modifyOrder); if (modifyResult == 1) { SCString message; message.Format("Trailing stop activated at price: %f", modifyOrder.Price1); sc.AddMessageToLog(message, 0); } else { SCString message; message.Format("Failed to modify stop order for trailing stop. Error: %d", modifyResult); sc.AddMessageToLog(message, 1); } } // Manage Breakeven Stop Logic if (!tradeInfo.stopMovedToBreakeven && tradeInfo.positionType != 0) { double breakevenPrice = tradeInfo.startPrice; if ((tradeInfo.positionType == 1 && sc.Close[sc.ArraySize - 1] >= breakevenPrice) || (tradeInfo.positionType == -1 && sc.Close[sc.ArraySize - 1] <= breakevenPrice)) { s_SCNewOrder modifyOrder; modifyOrder.InternalOrderID = tradeInfo.stopOrderID; modifyOrder.Price1 = breakevenPrice; int modifyResult = sc.ModifyOrder(modifyOrder); if (modifyResult == 1) { tradeInfo.stopMovedToBreakeven = true; SCString message; message.Format("Stop moved to breakeven at price: %f", modifyOrder.Price1); sc.AddMessageToLog(message, 0); } else { SCString message; message.Format("Failed to modify stop order to breakeven. Error: %d", modifyResult); sc.AddMessageToLog(message, 1); } } } // Additional Exit Logic: Any other conditions for exiting the trade can be added here } // End of trade management logic return; } |
[2024-08-08 10:27:12] |
User357489 - Posts: 72 |
PS in previous versions, i have been able to see the open position in the trade window attached to my DOM, and the relevant bracket order drawings it produces eg show order fills. Yet in this complication; the trade window is reading "FLAT" yet the pnl updates as trades are evidently opening and closing. Date Time Of Last Edit: 2024-08-08 10:27:38
|
[2024-08-08 10:34:22] |
User431178 - Posts: 540 |
At this point I would suggest installing Visual Studio and debugging step-by-step. Run the code and step through it so you can understand where/why it is failing/not doing what you expect. Step-By-Step ACSIL Debugging Either or add more logging messages to the code. Honestly I would recommend the setp-by-step debug, you will get a much better understanding of what is happening. Date Time Of Last Edit: 2024-08-08 10:35:30
|
[2024-08-08 12:16:29] |
User357489 - Posts: 72 |
No problem, will have a crack at that! Thank you friend, for your support! Will return with an update :) |
[2024-08-09 15:01:29] |
User357489 - Posts: 72 |
Ok i have taken an alternative approach; i already made a study that "highlights" when bid/ask pullingstacking value >= user defined threshold. #include "sierrachart.h"
SCDLLName("Flash Genie") SCSFExport scsf_FlashGenie(SCStudyInterfaceRef sc) { if (sc.SetDefaults) { sc.GraphName = "Flash Genie"; sc.GraphRegion = 0; sc.AutoLoop = 1; // Auto-loop enabled sc.Input[0].Name = "Volume Threshold"; sc.Input[0].SetInt(100); // Default threshold value sc.Input[1].Name = "Number of Levels"; sc.Input[1].SetInt(5); // Default number of levels sc.Input[2].Name = "Bid Highlight Color"; sc.Input[2].SetColor(RGB(0, 0, 255)); // Default bid highlight color sc.Input[3].Name = "Ask Highlight Color"; sc.Input[3].SetColor(RGB(255, 0, 0)); // Default ask highlight color return; } int threshold = sc.Input[0].GetInt(); int numLevels = sc.Input[1].GetInt(); COLORREF bidHighlightColor = sc.Input[2].GetColor(); COLORREF askHighlightColor = sc.Input[3].GetColor(); s_MarketDepthEntry depthEntry; // Remove existing highlights sc.DeleteACSChartDrawing(sc.ChartNumber, TOOL_DELETE_ALL, 0); for (int level = 0; level < numLevels; ++level) { // Check Ask levels if (sc.GetAskMarketDepthEntryAtLevel(depthEntry, level)) { double pullingStackingAsk = sc.GetAskMarketDepthStackPullValueAtPrice(depthEntry.Price); if (pullingStackingAsk >= threshold) { s_UseTool tool; tool.Clear(); tool.ChartNumber = sc.ChartNumber; tool.DrawingType = DRAWING_RECTANGLEHIGHLIGHT; tool.AddMethod = UTAM_ADD_OR_ADJUST; tool.BeginValue = depthEntry.Price - sc.TickSize / 2; tool.EndValue = depthEntry.Price + sc.TickSize / 2; tool.BeginDateTime = sc.BaseDateTimeIn[sc.ArraySize - 1]; tool.EndDateTime = sc.BaseDateTimeIn[0]; tool.Color = askHighlightColor; tool.SecondaryColor = askHighlightColor; tool.TransparencyLevel = 70; tool.LineWidth = 1; sc.UseTool(tool); } } // Check Bid levels if (sc.GetBidMarketDepthEntryAtLevel(depthEntry, level)) { double pullingStackingBid = sc.GetBidMarketDepthStackPullValueAtPrice(depthEntry.Price); if (pullingStackingBid >= threshold) { s_UseTool tool; tool.Clear(); tool.ChartNumber = sc.ChartNumber; tool.DrawingType = DRAWING_RECTANGLEHIGHLIGHT; tool.AddMethod = UTAM_ADD_OR_ADJUST; tool.BeginValue = depthEntry.Price - sc.TickSize / 2; tool.EndValue = depthEntry.Price + sc.TickSize / 2; tool.BeginDateTime = sc.BaseDateTimeIn[sc.ArraySize - 1]; tool.EndDateTime = sc.BaseDateTimeIn[0]; tool.Color = bidHighlightColor; tool.SecondaryColor = bidHighlightColor; tool.TransparencyLevel = 70; tool.LineWidth = 1; sc.UseTool(tool); } } } } so another bright idea was to replace the logic of checking the pullingstacking to the volume at price from the VBP (still set at askvolume-bidvolume), i spoonfed AI the sc.Get.... from the documentation and we created: #include "sierrachart.h" Kinda works, but doesnt work. please see attached screenshots. The user can input the StudyID for the VBP (i tried altering this and it indeed stopped highlighting completely so it recognised the VBP study - i think ) ps ignore the orange highlight, this is from the working study mentioned first. so you see it has highlighted all of the bid levels ( i realise in this example, the bid level VBP values are indeed all >0, however they dont "delete" when bid levels has VBP<0), however not included the ask levels and also the logic for vol>0, vol<0 hasnt been implemented correctly, if the VBP value on the bid levels is <0, then theres no need to highlight so ignore. likewise with VBP value on ask levels >0, ignore. so only ask levels will highlight when VBP values <0 and vice versa.SCDLLName("Volume Difference Highlight with Market Depth") SCSFExport scsf_VolumeDifferenceHighlightWithMarketDepth(SCStudyInterfaceRef sc) { if (sc.SetDefaults) { sc.GraphName = "Volume Difference Highlight with Market Depth"; sc.GraphRegion = 0; sc.AutoLoop = 1; sc.Input[0].Name = "Volume Profile Study ID"; sc.Input[0].SetInt(7); // Set this to the actual study ID of the Volume Profile sc.Input[1].Name = "Bid Highlight Color"; sc.Input[1].SetColor(RGB(0, 255, 0)); // Default bid highlight color sc.Input[2].Name = "Ask Highlight Color"; sc.Input[2].SetColor(RGB(255, 0, 0)); // Default ask highlight color sc.Input[3].Name = "Number of Levels to Check"; sc.Input[3].SetInt(5); // Number of bid/ask levels to check return; } int volumeProfileStudyID = sc.Input[0].GetInt(); COLORREF bidHighlightColor = sc.Input[1].GetColor(); COLORREF askHighlightColor = sc.Input[2].GetColor(); int numLevelsToCheck = sc.Input[3].GetInt(); s_MarketDepthEntry depthEntry; s_VolumeAtPriceV2 volumeAtPriceData; // Remove existing highlights sc.DeleteACSChartDrawing(sc.ChartNumber, TOOL_DELETE_ALL, 0); // Get the number of price levels in the VBP profile int numPriceLevels = sc.GetNumPriceLevelsForStudyProfile(volumeProfileStudyID, 0); // Loop through Ask levels and highlight based on volume difference for (int level = 0; level < numLevelsToCheck; ++level) { if (sc.GetAskMarketDepthEntryAtLevel(depthEntry, level)) { double price = depthEntry.Price; for (int priceIndex = 0; priceIndex < numPriceLevels; ++priceIndex) { if (sc.GetVolumeAtPriceDataForStudyProfile(volumeProfileStudyID, 0, priceIndex, volumeAtPriceData)) { double vbpPrice = volumeAtPriceData.PriceInTicks * sc.TickSize; if (fabs(vbpPrice - price) < sc.TickSize / 2) { double volumeDifference = volumeAtPriceData.AskVolume - volumeAtPriceData.BidVolume; if (volumeDifference < 0) // Highlight Ask levels with negative volume difference { s_UseTool tool; tool.Clear(); tool.ChartNumber = sc.ChartNumber; tool.DrawingType = DRAWING_RECTANGLEHIGHLIGHT; tool.AddMethod = UTAM_ADD_OR_ADJUST; tool.BeginValue = price - sc.TickSize / 2; tool.EndValue = price + sc.TickSize / 2; tool.BeginDateTime = sc.BaseDateTimeIn[sc.ArraySize - 1]; tool.EndDateTime = sc.BaseDateTimeIn[0]; tool.Color = askHighlightColor; tool.SecondaryColor = askHighlightColor; tool.TransparencyLevel = 70; tool.LineWidth = 1; sc.UseTool(tool); } break; } } } } } // Loop through Bid levels and highlight based on volume difference for (int level = 0; level < numLevelsToCheck; ++level) { if (sc.GetBidMarketDepthEntryAtLevel(depthEntry, level)) { double price = depthEntry.Price; for (int priceIndex = 0; priceIndex < numPriceLevels; ++priceIndex) { if (sc.GetVolumeAtPriceDataForStudyProfile(volumeProfileStudyID, 0, priceIndex, volumeAtPriceData)) { double vbpPrice = volumeAtPriceData.PriceInTicks * sc.TickSize; if (fabs(vbpPrice - price) < sc.TickSize / 2) { double volumeDifference = volumeAtPriceData.AskVolume - volumeAtPriceData.BidVolume; if (volumeDifference > 0) // Highlight Bid levels with positive volume difference { s_UseTool tool; tool.Clear(); tool.ChartNumber = sc.ChartNumber; tool.DrawingType = DRAWING_RECTANGLEHIGHLIGHT; tool.AddMethod = UTAM_ADD_OR_ADJUST; tool.BeginValue = price - sc.TickSize / 2; tool.EndValue = price + sc.TickSize / 2; tool.BeginDateTime = sc.BaseDateTimeIn[sc.ArraySize - 1]; tool.EndDateTime = sc.BaseDateTimeIn[0]; tool.Color = bidHighlightColor; tool.SecondaryColor = bidHighlightColor; tool.TransparencyLevel = 70; tool.LineWidth = 1; sc.UseTool(tool); } break; } } } } } } Gone over the docs and read thru what each member does and structure etc and hit the wall again (learning has taken place this week however thanks to your guidance and help! so again , TYVM!) EDIT: PS; taken this approach to make "standalone" conditions, make sure they work as intended, them throw them all together (logically of course) think ive been running before i can walk here, so this could prove a beneficial course of action Date Time Of Last Edit: 2024-08-09 15:04:56
|
image1.png / V - Attached On 2024-08-09 15:01:08 UTC - Size: 7.27 KB - 37 views |
[2024-08-09 15:54:30] |
User431178 - Posts: 540 |
double volumeDifference = volumeAtPriceData.AskVolume - volumeAtPriceData.BidVolume; Both volumeAtPriceData.AskVolume and volumeAtPriceData.BidVolume are unsigned integers (uint32_t), so you will not get a correct result if BV > AV. Even though you have the result as a double, the subtraction on the right hand side happens first, the result of which is then converted to double. For it to work correctly for negative numbers you would need to do somthing like one of the options below. double volumeDifference = (volumeAtPriceData.AskVolume * 1.0) - volumeAtPriceData.BidVolume; double volumeDifference = static_cast<double>(volumeAtPriceData.AskVolume) - volumeAtPriceData.BidVolume; int64_t volumeDifference = static_cast<int64_t>(volumeAtPriceData.AskVolume) - volumeAtPriceData.BidVolume; |
[2024-08-10 10:36:33] |
User357489 - Posts: 72 |
Beautiful thats worked, thanks pal! :)
|
[2024-08-12 08:06:12] |
User357489 - Posts: 72 |
Good morning, no rest for the wicked! Since breaking it down into smaller chunks so to speak, i have got 2 "entry" condition studies working as i wanted them to. So- i tried as best i could to take the logic from each one, and use them as entry conditions in the auto trading system; The build succeeded, however; its doing the same thing as before regarding trade mgt. PFA screenshots; 1 is the Trade DOM; so what i see is "FLAT" and the PNL is highlighted green, which it shouldnt if flat for a start, and the D:pnl box below, updates sporadically without seemingly opening a trade; ie i cant see the attached order fills on chart (the chart settings are correct) Here's the iteration of the auto trade, having taken the "highlighting" logic from the two other working code (attached as txt files for convenience) #include "sierrachart.h"
#include <unordered_map> #include <chrono> SCDLLName("Sweep Genie") struct TradeInfo { std::chrono::time_point<std::chrono::steady_clock> startTime; double startPrice; bool tradeEntered; int positionType; // 1 for buy, -1 for sell bool stopMovedToBreakeven; bool trailingStopActivated; int stopOrderID; }; std::unordered_map<int, TradeInfo> g_TradeInfo; void LogDebugMessage(SCStudyInterfaceRef& sc, const SCString& message) { sc.AddMessageToLog(message, 0); } void LogErrorMessage(SCStudyInterfaceRef& sc, const SCString& message) { sc.AddMessageToLog(message, 1); } void PlaceBracketOrder(SCStudyInterfaceRef& sc, TradeInfo& tradeInfo, int positionType, int orderQuantity, double price, int stopLossTicks, int takeProfitTicks) { s_SCNewOrder order; order.OrderType = SCT_ORDERTYPE_MARKET; order.OrderQuantity = orderQuantity; order.TimeInForce = SCT_TIF_DAY; // Define the attached orders order.Target1Offset = takeProfitTicks * sc.TickSize; order.Stop1Offset = stopLossTicks * sc.TickSize; // Set attached order types order.AttachedOrderTarget1Type = SCT_ORDERTYPE_LIMIT; order.AttachedOrderStop1Type = SCT_ORDERTYPE_STOP; int result = (positionType == 1) ? sc.BuyEntry(order) : sc.SellEntry(order); if (result > 0) { tradeInfo.startTime = std::chrono::steady_clock::now(); tradeInfo.startPrice = price; tradeInfo.tradeEntered = true; tradeInfo.positionType = positionType; tradeInfo.stopMovedToBreakeven = false; tradeInfo.trailingStopActivated = false; tradeInfo.stopOrderID = order.Stop1InternalOrderID; SCString message; message.Format("Trade entered: PositionType=%d, Price=%f", positionType, price); LogDebugMessage(sc, message); } else { SCString message; message.Format("Failed to enter trade: PositionType=%d, Error=%d", positionType, result); LogErrorMessage(sc, message); } } bool CheckFlashGenieHighlight(SCStudyInterfaceRef& sc, bool isBid) { int numLevels = sc.Input[1].GetInt(); double threshold = sc.Input[0].GetInt(); s_MarketDepthEntry depthEntry; for (int level = 0; level < numLevels; ++level) { if (isBid) { if (sc.GetBidMarketDepthEntryAtLevel(depthEntry, level)) { double pullingStackingBid = sc.GetBidMarketDepthStackPullValueAtPrice(depthEntry.Price); if (pullingStackingBid >= threshold) { LogDebugMessage(sc, "Flash Genie bid highlight condition met."); return true; } } } else { if (sc.GetAskMarketDepthEntryAtLevel(depthEntry, level)) { double pullingStackingAsk = sc.GetAskMarketDepthStackPullValueAtPrice(depthEntry.Price); if (pullingStackingAsk >= threshold) { LogDebugMessage(sc, "Flash Genie ask highlight condition met."); return true; } } } } return false; } bool CheckDeltaGenieHighlight(SCStudyInterfaceRef& sc, bool isBid) { int volumeProfileStudyID = sc.Input[0].GetInt(); int numLevelsToCheck = sc.Input[3].GetInt(); s_MarketDepthEntry depthEntry; s_VolumeAtPriceV2 volumeAtPriceData; for (int level = 0; level < numLevelsToCheck; ++level) { if (isBid) { if (sc.GetBidMarketDepthEntryAtLevel(depthEntry, level)) { for (int priceIndex = 0; priceIndex < sc.GetNumPriceLevelsForStudyProfile(volumeProfileStudyID, 0); ++priceIndex) { if (sc.GetVolumeAtPriceDataForStudyProfile(volumeProfileStudyID, 0, priceIndex, volumeAtPriceData)) { double vbpPrice = volumeAtPriceData.PriceInTicks * sc.TickSize; if (fabs(vbpPrice - depthEntry.Price) < sc.TickSize / 2) { if (volumeAtPriceData.AskVolume < volumeAtPriceData.BidVolume) { LogDebugMessage(sc, "Delta Genie bid highlight condition met."); return true; } } } } } } else { if (sc.GetAskMarketDepthEntryAtLevel(depthEntry, level)) { for (int priceIndex = 0; priceIndex < sc.GetNumPriceLevelsForStudyProfile(volumeProfileStudyID, 0); ++priceIndex) { if (sc.GetVolumeAtPriceDataForStudyProfile(volumeProfileStudyID, 0, priceIndex, volumeAtPriceData)) { double vbpPrice = volumeAtPriceData.PriceInTicks * sc.TickSize; if (fabs(vbpPrice - depthEntry.Price) < sc.TickSize / 2) { if (volumeAtPriceData.AskVolume > volumeAtPriceData.BidVolume) { LogDebugMessage(sc, "Delta Genie ask highlight condition met."); return true; } } } } } } } return false; } SCSFExport scsf_SweepGenie(SCStudyInterfaceRef sc) { if (sc.SetDefaults) { sc.GraphName = "Sweep Genie"; sc.GraphRegion = 0; sc.AutoLoop = 0; // Manual loop enabled // User inputs sc.Input[0].Name = "Use Start/Stop Time"; sc.Input[0].SetYesNo(0); // Default to No sc.Input[1].Name = "Start Time (HH:MM:SS)"; sc.Input[1].SetTime(HMS_TIME(9, 30, 0)); // Default start time sc.Input[2].Name = "Stop Time (HH:MM:SS)"; sc.Input[2].SetTime(HMS_TIME(16, 0, 0)); // Default stop time sc.Input[3].Name = "Volume Profile Study ID"; sc.Input[3].SetInt(7); // Set this to the actual study ID of the Volume Profile sc.Input[4].Name = "Order Quantity"; sc.Input[4].SetInt(1); sc.Input[5].Name = "Stop Loss Ticks"; sc.Input[5].SetInt(10); sc.Input[6].Name = "Take Profit Ticks"; sc.Input[6].SetInt(20); sc.Input[7].Name = "Trailing Stop Offset Ticks"; sc.Input[7].SetInt(5); sc.Input[8].Name = "Trade Type"; sc.Input[8].SetCustomInputStrings("Long;Short;Long & Short"); sc.Input[8].SetCustomInputIndex(2); // Default to Long & Short sc.Input[9].Name = "Maximum Positions Allowed"; sc.Input[9].SetInt(1); // Default to 1 position return; } bool useStartStopTime = sc.Input[0].GetYesNo(); SCDateTime startTime = sc.Input[1].GetTime(); SCDateTime stopTime = sc.Input[2].GetTime(); int volumeProfileStudyID = sc.Input[3].GetInt(); int orderQuantity = sc.Input[4].GetInt(); int stopLossTicks = sc.Input[5].GetInt(); int takeProfitTicks = sc.Input[6].GetInt(); int trailingStopOffsetTicks = sc.Input[7].GetInt(); int tradeType = sc.Input[8].GetIndex(); int maxPositionsAllowed = sc.Input[9].GetInt(); SCDateTime currentTime = sc.CurrentSystemDateTime; // Check if current time is within trading hours if (useStartStopTime && (currentTime < startTime || currentTime > stopTime)) { LogDebugMessage(sc, "Outside of trading hours. No trades will be executed."); return; } // Get current position size s_SCPositionData positionData; sc.GetTradePosition(positionData); int currentPosition = positionData.PositionQuantity; // Access the trade information auto& tradeInfo = g_TradeInfo[sc.ChartNumber]; bool buyConditionMet = false; bool sellConditionMet = false; double entryPrice = sc.Close[sc.ArraySize - 1]; // Using the current price for entry // Calculate the sum of bid and ask market depth quantities and pulling/stacking values double bidSum = 0.0; double askSum = 0.0; double pullingStackingBidSum = 0.0; double pullingStackingAskSum = 0.0; s_MarketDepthEntry depthEntry; for (int level = 0; level < sc.GetBidMarketDepthNumberOfLevels(); ++level) { if (sc.GetBidMarketDepthEntryAtLevel(depthEntry, level)) { bidSum += depthEntry.Quantity; pullingStackingBidSum += sc.GetBidMarketDepthStackPullValueAtPrice(depthEntry.Price); } } for (int level = 0; level < sc.GetAskMarketDepthNumberOfLevels(); ++level) { if (sc.GetAskMarketDepthEntryAtLevel(depthEntry, level)) { askSum += depthEntry.Quantity; pullingStackingAskSum += sc.GetAskMarketDepthStackPullValueAtPrice(depthEntry.Price); } } double totalDepthSum = bidSum + askSum; double bidSumPercentage = (totalDepthSum > 0) ? (bidSum / totalDepthSum) * 100 : 0; double askSumPercentage = (totalDepthSum > 0) ? (askSum / totalDepthSum) * 100 : 0; double bidPullStackPercentage = (pullingStackingBidSum / (pullingStackingBidSum + pullingStackingAskSum)) * 100; double askPullStackPercentage = (pullingStackingAskSum / (pullingStackingBidSum + pullingStackingAskSum)) * 100; // Buy Entry Conditions if (bidSumPercentage > askSumPercentage && // Bid sum percentage > ask sum percentage bidPullStackPercentage > askPullStackPercentage && // Bid pulling/stacking sum percentage > ask pulling/stacking sum percentage currentPosition < maxPositionsAllowed && // Current position below max positions allowed CheckFlashGenieHighlight(sc, true) && // Flash Genie bid highlight condition met CheckDeltaGenieHighlight(sc, true) && // Delta Genie bid highlight condition met tradeType != 1) // Long or Long & Short allowed { buyConditionMet = true; } // Sell Entry Conditions else if (askSumPercentage > bidSumPercentage && // Ask sum percentage > bid sum percentage askPullStackPercentage > bidPullStackPercentage && // Ask pulling/stacking sum percentage > bid pulling/stacking sum percentage currentPosition > -maxPositionsAllowed && // Current position below max positions allowed CheckFlashGenieHighlight(sc, false) && // Flash Genie ask highlight condition met CheckDeltaGenieHighlight(sc, false) && // Delta Genie ask highlight condition met tradeType != 0) // Short or Long & Short allowed { sellConditionMet = true; } // Execute Buy or Sell based on conditions if (buyConditionMet && !tradeInfo.tradeEntered) { PlaceBracketOrder(sc, tradeInfo, 1, orderQuantity, entryPrice, stopLossTicks, takeProfitTicks); } else if (sellConditionMet && !tradeInfo.tradeEntered) { PlaceBracketOrder(sc, tradeInfo, -1, orderQuantity, entryPrice, stopLossTicks, takeProfitTicks); } // Rest of the trade management logic if (tradeInfo.tradeEntered) { double stopLossPrice = tradeInfo.startPrice - (tradeInfo.positionType * stopLossTicks * sc.TickSize); double takeProfitPrice = tradeInfo.startPrice + (tradeInfo.positionType * takeProfitTicks * sc.TickSize); double trailingStopTriggerPrice = tradeInfo.startPrice + (tradeInfo.positionType * takeProfitTicks * 0.7 * sc.TickSize); // Check for stop loss or take profit condition if ((tradeInfo.positionType == 1 && (sc.Close[sc.ArraySize - 1] <= stopLossPrice || sc.Close[sc.ArraySize - 1] >= takeProfitPrice)) || (tradeInfo.positionType == -1 && (sc.Close[sc.ArraySize - 1] >= stopLossPrice || sc.Close[sc.ArraySize - 1] <= takeProfitPrice))) { sc.FlattenAndCancelAllOrders(); tradeInfo.tradeEntered = false; tradeInfo.positionType = 0; SCString message; message.Format("Trade exited: PositionType=%d, Price=%f", tradeInfo.positionType, sc.Close[sc.ArraySize - 1]); LogDebugMessage(sc, message); } else if (!tradeInfo.trailingStopActivated && tradeInfo.stopOrderID > 0 && ((tradeInfo.positionType == 1 && sc.Close[sc.ArraySize - 1] >= trailingStopTriggerPrice) || (tradeInfo.positionType == -1 && sc.Close[sc.ArraySize - 1] <= trailingStopTriggerPrice))) { tradeInfo.trailingStopActivated = true; s_SCNewOrder modifyOrder; modifyOrder.InternalOrderID = tradeInfo.stopOrderID; modifyOrder.Price1 = tradeInfo.startPrice + (tradeInfo.positionType * trailingStopOffsetTicks * sc.TickSize); int modifyResult = sc.ModifyOrder(modifyOrder); if (modifyResult == 1) { SCString message; message.Format("Trailing stop activated at price: %f", modifyOrder.Price1); LogDebugMessage(sc, message); } else { SCString message; message.Format("Failed to modify stop order for trailing stop. Error: %d", modifyResult); LogErrorMessage(sc, message); } } // Manage Breakeven Stop Logic if (!tradeInfo.stopMovedToBreakeven && tradeInfo.positionType != 0) { double breakevenPrice = tradeInfo.startPrice; if ((tradeInfo.positionType == 1 && sc.Close[sc.ArraySize - 1] >= breakevenPrice) || (tradeInfo.positionType == -1 && sc.Close[sc.ArraySize - 1] <= breakevenPrice)) { s_SCNewOrder modifyOrder; modifyOrder.InternalOrderID = tradeInfo.stopOrderID; modifyOrder.Price1 = breakevenPrice; int modifyResult = sc.ModifyOrder(modifyOrder); if (modifyResult == 1) { tradeInfo.stopMovedToBreakeven = true; SCString message; message.Format("Stop moved to breakeven at price: %f", modifyOrder.Price1); LogDebugMessage(sc, message); } else { SCString message; message.Format("Failed to modify stop order to breakeven. Error: %d", modifyResult); LogErrorMessage(sc, message); } } } // Additional Exit Logic: Any other conditions for exiting the trade can be added here } // End of trade management logic return; } its almost like it is on "auto DRAIN" mode haha, i added the condition of sumbidmarketdepth/sumask marketdepth comparisons to try bolster and make entry logic a bit more robust, but unsure as to why its buggering up, because its like it isnt giving the trade a chance , i wanted to add sum bid mbo >/<sumask mbo or something to that effect (as in a sum of all bid/ask mbo queues over X levels), again to try make the system differentiatie between a buy and a sell without it consistently drawing down while appearing FLAT, almost like daylight robbery. Date Time Of Last Edit: 2024-08-12 11:35:42
|
flashgeniebymrb.txt - Attached On 2024-08-12 08:04:42 UTC - Size: 3.17 KB - 121 views deltageniebymrb.txt - Attached On 2024-08-12 08:04:55 UTC - Size: 5.19 KB - 118 views |
To post a message in this thread, you need to log in with your Sierra Chart account: