Support Board
Date/Time: Sat, 23 Nov 2024 18:21:31 +0000
[Programming Help] - ACSIL Custom Autotrading System assistance
View Count: 1815
[2024-08-06 09:42:00] |
User357489 - Posts: 72 |
Hi SC Engineering Im a novice and hit a brick wall. I have a working version of my autotrader, and i had a "bright idea" of tweaking it (outlined in the attached explanation text file) I have the following iteration of my tweaks, and it provides several horrific looking errors and a failed build. I feel it may be something "obvious" but for more experienced eyes, so would appreciate the help. #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 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; order.Target1Offset = takeProfitTicks * sc.TickSize; order.Stop1Offset = stopLossTicks * sc.TickSize; 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 = 1; 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); 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(); SCDateTime currentTime = sc.CurrentSystemDateTime; auto& tradeInfo = g_TradeInfo[sc.ChartNumber]; s_SCPositionData positionData; sc.GetTradePosition(positionData); int currentPosition = positionData.PositionQuantity; double currentPrice = sc.Close[sc.ArraySize - 1]; bool buyConditionMet = false; bool sellConditionMet = false; double bidMboOrderSum = 0; double askMboOrderSum = 0; // Check top 5 bid levels for (int level = 0; level < 5; ++level) { s_MarketDepthEntry bidDepthEntry(0); // Initialize with dummy value if (sc.GetBidMarketDepthEntryAtLevel(level, bidDepthEntry)) { const s_VolumeAtPriceV2* volumeAtPrice = nullptr; int priceIndex = 0; if (sc.VolumeAtPriceForBars->GetPriceIndexForPrice(sc.ArraySize - 1, bidDepthEntry.Price, priceIndex)) { sc.VolumeAtPriceForBars->GetVAPElementAtIndex(sc.ArraySize - 1, priceIndex, &volumeAtPrice, false); if (volumeAtPrice && bidDepthEntry.StackPullValue >= volumeThreshold && (volumeAtPrice->AskVolume - volumeAtPrice->BidVolume) > 0) { buyConditionMet = true; } } } } // Check top 5 ask levels for (int level = 0; level < 5; ++level) { s_MarketDepthEntry askDepthEntry(0); // Initialize with dummy value if (sc.GetAskMarketDepthEntryAtLevel(level, askDepthEntry)) { const s_VolumeAtPriceV2* volumeAtPrice = nullptr; int priceIndex = 0; if (sc.VolumeAtPriceForBars->GetPriceIndexForPrice(sc.ArraySize - 1, askDepthEntry.Price, priceIndex)) { sc.VolumeAtPriceForBars->GetVAPElementAtIndex(sc.ArraySize - 1, priceIndex, &volumeAtPrice, false); if (volumeAtPrice && askDepthEntry.StackPullValue >= volumeThreshold && (volumeAtPrice->AskVolume - volumeAtPrice->BidVolume) < 0) { sellConditionMet = true; } } } } // Final conditions: Only enter a trade if MBO conditions are also met if (buyConditionMet && bidMboOrderSum > askMboOrderSum) { PlaceBracketOrder(sc, tradeInfo, 1, orderQuantity, currentPrice, stopLossTicks, takeProfitTicks); } else if (sellConditionMet && askMboOrderSum > bidMboOrderSum) { PlaceBracketOrder(sc, tradeInfo, -1, orderQuantity, currentPrice, stopLossTicks, takeProfitTicks); } // Exit conditions and trailing stop management 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 && (currentPrice <= stopLossPrice || currentPrice >= takeProfitPrice)) || (tradeInfo.positionType == -1 && (currentPrice >= stopLossPrice || currentPrice <= takeProfitPrice))) { sc.FlattenAndCancelAllOrders(); tradeInfo.tradeEntered = false; tradeInfo.positionType = 0; } else if (!tradeInfo.trailingStopActivated && tradeInfo.stopOrderID > 0 && ((tradeInfo.positionType == 1 && currentPrice >= trailingStopTriggerPrice) || (tradeInfo.positionType == -1 && currentPrice <= 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 && currentPrice >= breakevenPrice) || (tradeInfo.positionType == -1 && currentPrice <= 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); } } } } return; } Please also find attached the text file of my working iteration. |
Explanations.txt - Attached On 2024-08-06 09:38:28 UTC - Size: 4.3 KB - 643 views SweepGenieMrB.txt - Attached On 2024-08-06 09:41:39 UTC - Size: 6.66 KB - 635 views |
[2024-08-06 09:45:57] |
User357489 - Posts: 72 |
Without bombarding the board with all the errors; they are pertaining to getting the market depth data and vbp data; error: cannot bind non-const lvalue reference of type 's_MarketDepthEntry&' to an rvalue of type 's_MarketDepthEntry' 121 | if (sc.GetAskMarketDepthEntryAtLevel(level, askDepthEntry)) | ^~~~~ In file included from scstructures.h:104, |
[2024-08-06 10:18:39] |
User431178 - Posts: 541 |
s_MarketDepthEntry bidDepthEntry(0); // Initialize with dummy value
Remove the (0) s_MarketDepthEntry only has a default constructor (which takes no parameters). When it is constructed both member variables are zero initialized anyway. sc.VolumeAtPriceForBars->GetPriceIndexForPrice(sc.ArraySize - 1, askDepthEntry.Price, priceIndex))
This is a non-existant function, is it a ChatGPT hallucination? Try lookng at sc.VolumeAtPriceForBars->GetVAPElementForPriceIfExists
orsc.VolumeAtPriceForBars->GetVAPElementAtPrice
When you use the vap container, the prices are in ticks, so you need to use sc.PriceValueToTicks to convert the price first. volumeAtPrice->AskVolume - volumeAtPrice->BidVolume) < 0
This won't work as these values are unsigned integers.Rather than subtracting and comparing to zero, why not compare the variables directly. Replace (volumeAtPrice->AskVolume - volumeAtPrice->BidVolume) < 0
with(volumeAtPrice->BidVolume > volumeAtPrice->AskVolume)
Replace (volumeAtPrice->AskVolume - volumeAtPrice->BidVolume) > 0
with(volumeAtPrice->AskVolume > volumeAtPrice->BidVolume)
If your code still does not compile, post all the remaining error messages. |
[2024-08-06 10:36:39] |
User357489 - Posts: 72 |
Hi there, appreciate the help! Yes admittedly, i thought ChatGPT (4o) would understand my desired modifications enough but not the cdase, which is fine, we're both learning! here's the errors: apologies for being slow, its a lot to take in hence AI assistance thus far -- Starting remote build of Custom Studies Source files: sweepgeniedeltacheck.cpp. 64-bit -- 11:34:23 Allow time for the server to compile the files and build the DLL. Server: https://build.sierrachart.com The remote build is complete. The build failed. sweepgeniedeltacheck.cpp: In function 'void scsf_SweepGenie(SCStudyInterfaceRef)': sweepgeniedeltacheck.cpp:101:46: error: cannot bind non-const lvalue reference of type 's_MarketDepthEntry&' to an rvalue of type 's_MarketDepthEntry' 101 | if (sc.GetBidMarketDepthEntryAtLevel(level, bidDepthEntry)) | ^~~~~ In file included from scstructures.h:104, from sierrachart.h:22, from sweepgeniedeltacheck.cpp:1: scconstants.h:1986:2: note: after user-defined conversion: 's_MarketDepthEntry::s_MarketDepthEntry(int)' 1986 | s_MarketDepthEntry(int DummyValue = 0) | ^~~~~~~~~~~~~~~~~~ sweepgeniedeltacheck.cpp:106:118: error: no matching function for call to 'c_VAPContainer::GetVAPElementForPriceIfExists(int, int&, const s_VolumeAtPriceV2**)' 106 | if (sc.VolumeAtPriceForBars->GetVAPElementForPriceIfExists(sc.ArraySize - 1, priceInTicks, &volumeAtPrice)) | ^ In file included from scstructures.h:108, from sierrachart.h:22, from sweepgeniedeltacheck.cpp:1: VAPContainer.h:630:13: note: candidate: 'bool c_VAPContainerBase<t_VolumeAtPrice>::GetVAPElementForPriceIfExists(unsigned int, int, t_VolumeAtPrice**, unsigned int&) [with t_VolumeAtPrice = s_VolumeAtPriceV2]' 630 | inline bool c_VAPContainerBase<t_VolumeAtPrice>::GetVAPElementForPriceIfExists | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ VAPContainer.h:630:13: note: candidate expects 4 arguments, 3 provided sweepgeniedeltacheck.cpp:108:35: error: 'struct s_MarketDepthEntry' has no member named 'PullingStacking' 108 | if (bidDepthEntry.PullingStacking > volumeThreshold && volumeAtPrice->AskVolume > volumeAtPrice->BidVolume) | ^~~~~~~~~~~~~~~ sweepgeniedeltacheck.cpp:121:46: error: cannot bind non-const lvalue reference of type 's_MarketDepthEntry&' to an rvalue of type 's_MarketDepthEntry' 121 | if (sc.GetAskMarketDepthEntryAtLevel(level, askDepthEntry)) | ^~~~~ In file included from scstructures.h:104, from sierrachart.h:22, from sweepgeniedeltacheck.cpp:1: scconstants.h:1986:2: note: after user-defined conversion: 's_MarketDepthEntry::s_MarketDepthEntry(int)' 1986 | s_MarketDepthEntry(int DummyValue = 0) | ^~~~~~~~~~~~~~~~~~ sweepgeniedeltacheck.cpp:126:118: error: no matching function for call to 'c_VAPContainer::GetVAPElementForPriceIfExists(int, int&, const s_VolumeAtPriceV2**)' 126 | if (sc.VolumeAtPriceForBars->GetVAPElementForPriceIfExists(sc.ArraySize - 1, priceInTicks, &volumeAtPrice)) | ^ In file included from scstructures.h:108, from sierrachart.h:22, from sweepgeniedeltacheck.cpp:1: VAPContainer.h:630:13: note: candidate: 'bool c_VAPContainerBase<t_VolumeAtPrice>::GetVAPElementForPriceIfExists(unsigned int, int, t_VolumeAtPrice**, unsigned int&) [with t_VolumeAtPrice = s_VolumeAtPriceV2]' 630 | inline bool c_VAPContainerBase<t_VolumeAtPrice>::GetVAPElementForPriceIfExists | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ VAPContainer.h:630:13: note: candidate expects 4 arguments, 3 provided sweepgeniedeltacheck.cpp:128:35: error: 'struct s_MarketDepthEntry' has no member named 'PullingStacking' 128 | if (askDepthEntry.PullingStacking > volumeThreshold && volumeAtPrice->BidVolume > volumeAtPrice->AskVolume) | ^~~~~~~~~~~~~~~ -- End of Build -- 11:34:27 I have looked through the documentation, but i'm having difficulty applying it without guidance |
[2024-08-06 10:37:50] |
User357489 - Posts: 72 |
FYI, these errors have been the main issue, among several attempts, so have been going back and forth to no avail at present
|
[2024-08-06 11:20:04] |
User431178 - Posts: 541 |
If you have edited the code already, please post it. Replace this s_MarketDepthEntry bidDepthEntry(0); // Initialize with dummy value
and thiss_MarketDepthEntry askDepthEntry(0); // Initialize with dummy value
with s_MarketDepthEntry bidDepthEntry;
ands_MarketDepthEntry askDepthEntry;
That should fix the first errors. To get pull stack values, you need to call separate functions. sc.GetBidMarketDepthStackPullValueAtPrice sc.GetAskMarketDepthStackPullValueAtPrice sc.GetBidMarketDepthStackPullValueAtPrice() Once those errors are fixed, post the code and we fix the VAP errors. Date Time Of Last Edit: 2024-08-06 11:20:42
|
[2024-08-06 11:27:15] |
User357489 - Posts: 72 |
implementing the above: #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 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 = 1; 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); 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(); SCDateTime currentTime = sc.CurrentSystemDateTime; auto& tradeInfo = g_TradeInfo[sc.ChartNumber]; s_SCPositionData positionData; sc.GetTradePosition(positionData); int currentPosition = positionData.PositionQuantity; double currentPrice = sc.Close[sc.ArraySize - 1]; bool buyConditionMet = false; bool sellConditionMet = false; double bidMboOrderSum = 0; double askMboOrderSum = 0; // Check top 5 bid levels for (int level = 0; level < 5; ++level) { s_MarketDepthEntry bidDepthEntry; // Default initialization if (sc.GetBidMarketDepthEntryAtLevel(level, bidDepthEntry)) { const s_VolumeAtPriceV2* volumeAtPrice = nullptr; int priceInTicks = sc.PriceValueToTicks(bidDepthEntry.Price); if (sc.VolumeAtPriceForBars->GetVAPElementForPriceIfExists(sc.ArraySize - 1, priceInTicks, &volumeAtPrice)) { double bidPullingStacking = sc.GetBidMarketDepthStackPullValueAtPrice(bidDepthEntry.Price); if (bidPullingStacking >= volumeThreshold && volumeAtPrice->AskVolume > volumeAtPrice->BidVolume) { buyConditionMet = true; } } } } // Check top 5 ask levels for (int level = 0; level < 5; ++level) { s_MarketDepthEntry askDepthEntry; // Default initialization if (sc.GetAskMarketDepthEntryAtLevel(level, askDepthEntry)) { const s_VolumeAtPriceV2* volumeAtPrice = nullptr; int priceInTicks = sc.PriceValueToTicks(askDepthEntry.Price); if (sc.VolumeAtPriceForBars->GetVAPElementForPriceIfExists(sc.ArraySize - 1, priceInTicks, &volumeAtPrice)) { double askPullingStacking = sc.GetAskMarketDepthStackPullValueAtPrice(askDepthEntry.Price); if (askPullingStacking >= volumeThreshold && volumeAtPrice->BidVolume > volumeAtPrice->AskVolume) { sellConditionMet = true; } } } } // Final conditions: Only enter a trade if MBO conditions are also met if (buyConditionMet && bidMboOrderSum > askMboOrderSum) { PlaceBracketOrder(sc, tradeInfo, 1, orderQuantity, currentPrice, stopLossTicks, takeProfitTicks); } else if (sellConditionMet && askMboOrderSum > bidMboOrderSum) { PlaceBracketOrder(sc, tradeInfo, -1, orderQuantity, currentPrice, stopLossTicks, takeProfitTicks); } // Exit conditions and trailing stop management 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 && (currentPrice <= stopLossPrice || currentPrice >= takeProfitPrice)) || (tradeInfo.positionType == -1 && (currentPrice >= stopLossPrice || currentPrice <= takeProfitPrice))) { sc.FlattenAndCancelAllOrders(); tradeInfo.tradeEntered = false; tradeInfo.positionType = 0; } else if (!tradeInfo.trailingStopActivated && tradeInfo.stopOrderID > 0 && ((tradeInfo.positionType == 1 && currentPrice >= trailingStopTriggerPrice) || (tradeInfo.positionType == -1 && currentPrice <= 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 && currentPrice >= breakevenPrice) || (tradeInfo.positionType == -1 && currentPrice <= 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); } } } } // End of trade management logic return; } This returned: -- Starting remote build of Custom Studies Source files: sweepgeniedeltacheck.cpp. 64-bit -- 12:26:42 Allow time for the server to compile the files and build the DLL. Server: https://build2.sierrachart.com The remote build is complete. The build failed. sweepgeniedeltacheck.cpp: In function 'void scsf_SweepGenie(SCStudyInterfaceRef)': sweepgeniedeltacheck.cpp:101:46: error: cannot bind non-const lvalue reference of type 's_MarketDepthEntry&' to an rvalue of type 's_MarketDepthEntry' 101 | if (sc.GetBidMarketDepthEntryAtLevel(level, bidDepthEntry)) | ^~~~~ In file included from scstructures.h:104, from sierrachart.h:22, from sweepgeniedeltacheck.cpp:1: scconstants.h:1986:2: note: after user-defined conversion: 's_MarketDepthEntry::s_MarketDepthEntry(int)' 1986 | s_MarketDepthEntry(int DummyValue = 0) | ^~~~~~~~~~~~~~~~~~ sweepgeniedeltacheck.cpp:106:118: error: no matching function for call to 'c_VAPContainer::GetVAPElementForPriceIfExists(int, int&, const s_VolumeAtPriceV2**)' 106 | if (sc.VolumeAtPriceForBars->GetVAPElementForPriceIfExists(sc.ArraySize - 1, priceInTicks, &volumeAtPrice)) | ^ In file included from scstructures.h:108, from sierrachart.h:22, from sweepgeniedeltacheck.cpp:1: VAPContainer.h:630:13: note: candidate: 'bool c_VAPContainerBase<t_VolumeAtPrice>::GetVAPElementForPriceIfExists(unsigned int, int, t_VolumeAtPrice**, unsigned int&) [with t_VolumeAtPrice = s_VolumeAtPriceV2]' 630 | inline bool c_VAPContainerBase<t_VolumeAtPrice>::GetVAPElementForPriceIfExists | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ VAPContainer.h:630:13: note: candidate expects 4 arguments, 3 provided sweepgeniedeltacheck.cpp:122:46: error: cannot bind non-const lvalue reference of type 's_MarketDepthEntry&' to an rvalue of type 's_MarketDepthEntry' 122 | if (sc.GetAskMarketDepthEntryAtLevel(level, askDepthEntry)) | ^~~~~ In file included from scstructures.h:104, from sierrachart.h:22, from sweepgeniedeltacheck.cpp:1: scconstants.h:1986:2: note: after user-defined conversion: 's_MarketDepthEntry::s_MarketDepthEntry(int)' 1986 | s_MarketDepthEntry(int DummyValue = 0) | ^~~~~~~~~~~~~~~~~~ sweepgeniedeltacheck.cpp:127:118: error: no matching function for call to 'c_VAPContainer::GetVAPElementForPriceIfExists(int, int&, const s_VolumeAtPriceV2**)' 127 | if (sc.VolumeAtPriceForBars->GetVAPElementForPriceIfExists(sc.ArraySize - 1, priceInTicks, &volumeAtPrice)) | ^ In file included from scstructures.h:108, from sierrachart.h:22, from sweepgeniedeltacheck.cpp:1: VAPContainer.h:630:13: note: candidate: 'bool c_VAPContainerBase<t_VolumeAtPrice>::GetVAPElementForPriceIfExists(unsigned int, int, t_VolumeAtPrice**, unsigned int&) [with t_VolumeAtPrice = s_VolumeAtPriceV2]' 630 | inline bool c_VAPContainerBase<t_VolumeAtPrice>::GetVAPElementForPriceIfExists | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ VAPContainer.h:630:13: note: candidate expects 4 arguments, 3 provided -- End of Build -- 12:26:46 |
[2024-08-06 13:29:22] |
User431178 - Posts: 541 |
if (sc.GetBidMarketDepthEntryAtLevel(level, bidDepthEntry))
if (sc.GetAskMarketDepthEntryAtLevel(level, askDepthEntry))
Sorry, missed this before, the parameters are the wrong way around in those lines above, should be depth struct followed by level index. sc.GetAskMarketDepthEntryAtLevel Date Time Of Last Edit: 2024-08-06 13:29:47
|
[2024-08-06 13:38:11] |
User357489 - Posts: 72 |
ok so this: #include "sierrachart.h" , now only seems to return issues with VAP, so i think Market depth may have been solved (THANKYOU SO FAR! lifesaver)#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 = 1; 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); 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(); SCDateTime currentTime = sc.CurrentSystemDateTime; auto& tradeInfo = g_TradeInfo[sc.ChartNumber]; s_SCPositionData positionData; sc.GetTradePosition(positionData); int currentPosition = positionData.PositionQuantity; double currentPrice = sc.Close[sc.ArraySize - 1]; bool buyConditionMet = false; bool sellConditionMet = false; double bidMboOrderSum = 0; double askMboOrderSum = 0; // Check top 5 bid levels for (int level = 0; level < 5; ++level) { s_MarketDepthEntry bidDepthEntry; // Default initialization if (sc.GetBidMarketDepthEntryAtLevel(bidDepthEntry, level)) { const s_VolumeAtPriceV2* volumeAtPrice = nullptr; int priceInTicks = sc.PriceValueToTicks(bidDepthEntry.Price); unsigned int unusedVar; // An unused variable to meet the function signature if (sc.VolumeAtPriceForBars->GetVAPElementForPriceIfExists(sc.ArraySize - 1, priceInTicks, &volumeAtPrice, unusedVar)) { double bidPullingStacking = sc.GetBidMarketDepthStackPullValueAtPrice(bidDepthEntry.Price); if (bidPullingStacking >= volumeThreshold && volumeAtPrice->AskVolume > volumeAtPrice->BidVolume) { buyConditionMet = true; } } } } // Check top 5 ask levels for (int level = 0; level < 5; ++level) { s_MarketDepthEntry askDepthEntry; // Default initialization if (sc.GetAskMarketDepthEntryAtLevel(askDepthEntry, level)) { const s_VolumeAtPriceV2* volumeAtPrice = nullptr; int priceInTicks = sc.PriceValueToTicks(askDepthEntry.Price); unsigned int unusedVar; // An unused variable to meet the function signature if (sc.VolumeAtPriceForBars->GetVAPElementForPriceIfExists(sc.ArraySize - 1, priceInTicks, &volumeAtPrice, unusedVar)) { double askPullingStacking = sc.GetAskMarketDepthStackPullValueAtPrice(askDepthEntry.Price); if (askPullingStacking >= volumeThreshold && volumeAtPrice->BidVolume > volumeAtPrice->AskVolume) { sellConditionMet = true; } } } } // Final conditions: Only enter a trade if MBO conditions are also met if (buyConditionMet && bidMboOrderSum > askMboOrderSum) { PlaceBracketOrder(sc, tradeInfo, 1, orderQuantity, currentPrice, stopLossTicks, takeProfitTicks); } else if (sellConditionMet && askMboOrderSum > bidMboOrderSum) { PlaceBracketOrder(sc, tradeInfo, -1, orderQuantity, currentPrice, stopLossTicks, takeProfitTicks); } // Exit conditions and trailing stop management 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 && (currentPrice <= stopLossPrice || currentPrice >= takeProfitPrice)) || (tradeInfo.positionType == -1 && (currentPrice >= stopLossPrice || currentPrice <= takeProfitPrice))) { sc.FlattenAndCancelAllOrders(); tradeInfo.tradeEntered = false; tradeInfo.positionType = 0; } else if (!tradeInfo.trailingStopActivated && tradeInfo.stopOrderID > 0 && ((tradeInfo.positionType == 1 && currentPrice >= trailingStopTriggerPrice) || (tradeInfo.positionType == -1 && currentPrice <= 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 && currentPrice >= breakevenPrice) || (tradeInfo.positionType == -1 && currentPrice <= 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); } } } } // End of trade management logic return; } -- Starting remote build of Custom Studies Source files: sweepgeniehelp1.cpp. 64-bit -- 14:37:12 Allow time for the server to compile the files and build the DLL. Server: https://build2.sierrachart.com The remote build is complete. The build failed. sweepgeniehelp1.cpp: In function 'void scsf_SweepGenie(SCStudyInterfaceRef)': sweepgeniehelp1.cpp:107:104: error: invalid conversion from 'const s_VolumeAtPriceV2**' to 's_VolumeAtPriceV2**' [-fpermissive] 107 | if (sc.VolumeAtPriceForBars->GetVAPElementForPriceIfExists(sc.ArraySize - 1, priceInTicks, &volumeAtPrice, unusedVar)) | ^~~~~~~~~~~~~~ | | | const s_VolumeAtPriceV2** In file included from scstructures.h:108, from sierrachart.h:22, from sweepgeniehelp1.cpp:1: VAPContainer.h:633:21: note: initializing argument 3 of 'bool c_VAPContainerBase<t_VolumeAtPrice>::GetVAPElementForPriceIfExists(unsigned int, int, t_VolumeAtPrice**, unsigned int&) [with t_VolumeAtPrice = s_VolumeAtPriceV2]' 633 | , t_VolumeAtPrice** p_VAP | ~~~~~~~~~~~~~~~~~~^~~~~ sweepgeniehelp1.cpp:129:104: error: invalid conversion from 'const s_VolumeAtPriceV2**' to 's_VolumeAtPriceV2**' [-fpermissive] 129 | if (sc.VolumeAtPriceForBars->GetVAPElementForPriceIfExists(sc.ArraySize - 1, priceInTicks, &volumeAtPrice, unusedVar)) | ^~~~~~~~~~~~~~ | | | const s_VolumeAtPriceV2** In file included from scstructures.h:108, from sierrachart.h:22, from sweepgeniehelp1.cpp:1: VAPContainer.h:633:21: note: initializing argument 3 of 'bool c_VAPContainerBase<t_VolumeAtPrice>::GetVAPElementForPriceIfExists(unsigned int, int, t_VolumeAtPrice**, unsigned int&) [with t_VolumeAtPrice = s_VolumeAtPriceV2]' 633 | , t_VolumeAtPrice** p_VAP | ~~~~~~~~~~~~~~~~~~^~~~~ -- End of Build -- 14:37:16 |
[2024-08-06 13:51:35] |
User357489 - Posts: 72 |
PS the reason i wanted to use vap>0/<0: please see attached screenshot (far left col), changing the VBP study to Ask vol- bid Vol to display, the premise being the system will only enter longs/shorts at prices where delta >0/<0, does this make sense, |
[2024-08-06 14:45:54] |
User431178 - Posts: 541 |
please see attached screenshot (far left col), changing the VBP study to Ask vol- bid Vol to display, the premise being the system will only enter longs/shorts at prices where delta >0/<0, does this make sense, So do you want to know whether the current bar has +/- delta at price or the volume profile? sweepgeniehelp1.cpp: In function 'void scsf_SweepGenie(SCStudyInterfaceRef)': sweepgeniehelp1.cpp:107:104: error: invalid conversion from 'const s_VolumeAtPriceV2**' to 's_VolumeAtPriceV2**' [-fpermissive] 107 | if (sc.VolumeAtPriceForBars->GetVAPElementForPriceIfExists(sc.ArraySize - 1, priceInTicks, &volumeAtPrice, unusedVar)) This means that you need to drop the const prefix from here const s_VolumeAtPriceV2* volumeAtPrice = nullptr;
Another option would be to use GetVAPElementAtPrice which returns a const reference to the VAP object (which is empty if not found). const auto& vap = sc.VolumeAtPriceForBars->GetVAPElementAtPrice(sc.ArraySize - 1, priceInTicks); if (!vap.IsEmpty()) { double askPullingStacking = sc.GetAskMarketDepthStackPullValueAtPrice(askDepthEntry.Price); if (askPullingStacking >= volumeThreshold && volumeAtPrice->BidVolume > volumeAtPrice->AskVolume) { sellConditionMet = true; } } The member functions for vapcontainer are mentioned here - ACSIL Interface Members - Variables and Arrays: sc.VolumeAtPriceForBars Member Function Descriptions You would also want to add the below to your setdefaults section. sc.scMaintainVolumeAtPriceData = 1;
ACSIL Interface Members - Variables and Arrays: sc.MaintainVolumeAtPriceData |
[2024-08-06 14:49:19] |
User357489 - Posts: 72 |
"So do you want to know whether the current bar has +/- delta at price or the volume profile?" the volume profile at price- i wanted the condition that "if the price level delta from vol profile >0 AND bid pulling stacking (over 5 bid levels)>=threshold, if so then buy. to differentiate bogus entries entering long when the price level has a displayed delta volume of -1000 for sake of argument. |
[2024-08-06 14:55:25] |
User357489 - Posts: 72 |
#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 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.MaintainVolumeAtPriceData = 1; // Ensure VolumeAtPrice data is maintained 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(); SCDateTime currentTime = sc.CurrentSystemDateTime; auto& tradeInfo = g_TradeInfo[sc.ChartNumber]; s_SCPositionData positionData; sc.GetTradePosition(positionData); int currentPosition = positionData.PositionQuantity; double currentPrice = sc.Close[sc.ArraySize - 1]; bool buyConditionMet = false; bool sellConditionMet = false; double bidMboOrderSum = 0; double askMboOrderSum = 0; // Check top 5 bid levels for (int level = 0; level < 5; ++level) { s_MarketDepthEntry bidDepthEntry; if (sc.GetBidMarketDepthEntryAtLevel(bidDepthEntry, level)) { int priceInTicks = sc.PriceValueToTicks(bidDepthEntry.Price); const auto& volumeAtPrice = sc.VolumeAtPriceForBars->GetVAPElementAtPrice(sc.ArraySize - 1, priceInTicks); if (!volumeAtPrice.IsEmpty()) { double bidPullingStacking = sc.GetBidMarketDepthStackPullValueAtPrice(bidDepthEntry.Price); if (bidPullingStacking >= volumeThreshold && volumeAtPrice.AskVolume > volumeAtPrice.BidVolume) { buyConditionMet = true; } } } } // Check top 5 ask levels for (int level = 0; level < 5; ++level) { s_MarketDepthEntry askDepthEntry; if (sc.GetAskMarketDepthEntryAtLevel(askDepthEntry, level)) { int priceInTicks = sc.PriceValueToTicks(askDepthEntry.Price); const auto& volumeAtPrice = sc.VolumeAtPriceForBars->GetVAPElementAtPrice(sc.ArraySize - 1, priceInTicks); if (!volumeAtPrice.IsEmpty()) { double askPullingStacking = sc.GetAskMarketDepthStackPullValueAtPrice(askDepthEntry.Price); if (askPullingStacking >= volumeThreshold && volumeAtPrice.BidVolume > volumeAtPrice.AskVolume) { sellConditionMet = true; } } } } // Final conditions: Only enter a trade if MBO conditions are also met if (buyConditionMet && bidMboOrderSum > askMboOrderSum) { PlaceBracketOrder(sc, tradeInfo, 1, orderQuantity, currentPrice, stopLossTicks, takeProfitTicks); } else if (sellConditionMet && askMboOrderSum > bidMboOrderSum) { PlaceBracketOrder(sc, tradeInfo, -1, orderQuantity, currentPrice, stopLossTicks, takeProfitTicks); } // Exit conditions and trailing stop management 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 && (currentPrice <= stopLossPrice || currentPrice >= takeProfitPrice)) || (tradeInfo.positionType == -1 && (currentPrice >= stopLossPrice || currentPrice <= takeProfitPrice))) { sc.FlattenAndCancelAllOrders(); tradeInfo.tradeEntered = false; tradeInfo.positionType = 0; } else if (!tradeInfo.trailingStopActivated && tradeInfo.stopOrderID > 0 && ((tradeInfo.positionType == 1 && currentPrice >= trailingStopTriggerPrice) || (tradeInfo.positionType == -1 && currentPrice <= 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 && currentPrice >= breakevenPrice) || (tradeInfo.positionType == -1 && currentPrice <= 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); } } } } // End of trade management logic return; } This has resulted in a successful build! Now to see if it does what its supposed to do! I cannot thank you enough, anon user! If you have time please add me on discord; username campanariskman, if its okay with you would like to gain more knowledge with this so wanting to surround myself with those who know more |
[2024-08-06 15:17:11] |
User431178 - Posts: 541 |
the volume profile at price- i wanted the condition that "if the price level delta from vol profile >0 AND bid pulling stacking (over 5 bid levels)>=threshold, if so then buy. to differentiate bogus entries entering long when the price level has a displayed delta volume of -1000 for sake of argument. If you want to access the data from the volume profile a different approach is needed, the way the ocde is written it look only at the volume at price data within the current bar. |
[2024-08-06 15:32:26] |
User357489 - Posts: 72 |
i initially tried getarray for studyid, but for each of my trade doms, the study id is different, so that was to allow the user to select the vbp study, but didnt know if it had a subgraph reference and got stuck
|
[2024-08-06 15:58:31] |
User431178 - Posts: 541 |
i initially tried getarray for studyid, but for each of my trade doms, the study id is different, so that was to allow the user to select the vbp study, but didnt know if it had a subgraph reference and got stuck
You can use one of the inputs to select the coorect VBP studyID. ACSIL Interface Members - sc.Input Array: sc.Input[].GetStudyID() To get data for the VBP you would use this function. sc.GetVolumeAtPriceDataForStudyProfile() |
[2024-08-06 16:15:36] |
User357489 - Posts: 72 |
#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 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; double currentPrice = sc.Close[sc.ArraySize - 1]; bool buyConditionMet = false; bool sellConditionMet = false; double bidMboOrderSum = 0; double askMboOrderSum = 0; // Check top 5 bid levels for (int level = 0; level < 5; ++level) { s_MarketDepthEntry bidDepthEntry; // Default initialization if (sc.GetBidMarketDepthEntryAtLevel(bidDepthEntry, level)) { int priceInTicks = sc.PriceValueToTicks(bidDepthEntry.Price); s_VolumeAtPriceV2 volumeAtPrice; unsigned int volumeAtPriceIndex; if (sc.GetVolumeAtPriceDataForStudyProfile(vbpStudyID, priceInTicks, volumeAtPrice, volumeAtPriceIndex) == 1) { double bidPullingStacking = sc.GetBidMarketDepthStackPullValueAtPrice(bidDepthEntry.Price); if (bidPullingStacking >= volumeThreshold && volumeAtPrice.AskVolume > volumeAtPrice.BidVolume) { buyConditionMet = true; } } } } // Check top 5 ask levels for (int level = 0; level < 5; ++level) { s_MarketDepthEntry askDepthEntry; // Default initialization if (sc.GetAskMarketDepthEntryAtLevel(askDepthEntry, level)) { int priceInTicks = sc.PriceValueToTicks(askDepthEntry.Price); s_VolumeAtPriceV2 volumeAtPrice; unsigned int volumeAtPriceIndex; if (sc.GetVolumeAtPriceDataForStudyProfile(vbpStudyID, priceInTicks, volumeAtPrice, volumeAtPriceIndex) == 1) { double askPullingStacking = sc.GetAskMarketDepthStackPullValueAtPrice(askDepthEntry.Price); if (askPullingStacking >= volumeThreshold && volumeAtPrice.BidVolume > volumeAtPrice.AskVolume) { sellConditionMet = true; } } } } // Final conditions: Only enter a trade if MBO conditions are also met if (buyConditionMet && bidMboOrderSum > askMboOrderSum) { PlaceBracketOrder(sc, tradeInfo, 1, orderQuantity, currentPrice, stopLossTicks, takeProfitTicks); } else if (sellConditionMet && askMboOrderSum > bidMboOrderSum) { PlaceBracketOrder(sc, tradeInfo, -1, orderQuantity, currentPrice, stopLossTicks, takeProfitTicks); } // Exit conditions and trailing stop management 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 && (currentPrice <= stopLossPrice || currentPrice >= takeProfitPrice)) || (tradeInfo.positionType == -1 && (currentPrice >= stopLossPrice || currentPrice <= takeProfitPrice))) { sc.FlattenAndCancelAllOrders(); tradeInfo.tradeEntered = false; tradeInfo.positionType = 0; } else if (!tradeInfo.trailingStopActivated && tradeInfo.stopOrderID > 0 && ((tradeInfo.positionType == 1 && currentPrice >= trailingStopTriggerPrice) || (tradeInfo.positionType == -1 && currentPrice <= 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 && currentPrice >= breakevenPrice) || (tradeInfo.positionType == -1 && currentPrice <= 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; } applying the above returned: -- Starting remote build of Custom Studies Source files: sweepgeniehelp2.cpp. 64-bit -- 17:14:41 Allow time for the server to compile the files and build the DLL. Server: https://build2.sierrachart.com The remote build is complete. The build failed. sweepgeniehelp2.cpp: In function 'void scsf_SweepGenie(SCStudyInterfaceRef)': sweepgeniehelp2.cpp:112:82: error: cannot convert 's_VolumeAtPriceV2' to 'int' in argument passing 112 | if (sc.GetVolumeAtPriceDataForStudyProfile(vbpStudyID, priceInTicks, volumeAtPrice, volumeAtPriceIndex) == 1) | ^~~~~~~~~~~~~ | | | s_VolumeAtPriceV2 sweepgeniehelp2.cpp:135:82: error: cannot convert 's_VolumeAtPriceV2' to 'int' in argument passing 135 | if (sc.GetVolumeAtPriceDataForStudyProfile(vbpStudyID, priceInTicks, volumeAtPrice, volumeAtPriceIndex) == 1) | ^~~~~~~~~~~~~ | | | |
[2024-08-06 20:06:14] |
User431178 - Posts: 541 |
Yes, makes sense. Suggest reading this page again: sc.GetVolumeAtPriceDataForStudyProfile() sc.GetVolumeAtPriceDataForStudyProfile(vbpStudyID, priceInTicks, volumeAtPrice, volumeAtPriceIndex)
The above does not conform to the specification for that function. int GetVolumeAtPriceDataForStudyProfile(const int StudyID, const int ProfileIndex, const int PriceIndex, s_VolumeAtPriceV2& VolumeAtPrice);
ProfileIndex is, in this case, 0 as we are interested only in the most recent profile.For PriceIndex you actually need to loop through the available levels to find the one that you need. See if you can figure it out, if not I will try to help some more tomorrow. |
[2024-08-07 08:31:46] |
User357489 - Posts: 72 |
good morning! Thanks again your help is invaluable. Here was this mornings first attempt, followed by (what i thought) was a meaningful explanation to AI Please see attached and here was the prompt: "in this example, a buy trade would be opened at the current price (73.66, as the buy conditions have been met at 73.64 (the bidpullingstacking>=threshold - hence the blue highlight AND the volume profile number is a number>0. The opposite would be true for a sell, as you can see from this example however, the ask highlight (orange) meets the askpullingstacking threshold but does not meet the volume profile condition at the price (73.69) as the volume profile level has a positive integer |
file-84uSpCLirUlDuR0bxxefC5gt.png / V - Attached On 2024-08-07 08:30:37 UTC - Size: 18.4 KB - 31 views |
[2024-08-07 08:37:15] |
User357489 - Posts: 72 |
such a prompt returned a successsful build: #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 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; double currentPrice = sc.Close[sc.ArraySize - 1]; bool buyConditionMet = false; bool sellConditionMet = false; // Check Volume at Price data and Pulling/Stacking for entry conditions int priceInTicks = sc.PriceValueToTicks(currentPrice); int profileIndex = 0; // Use 0 for the most recent profile s_VolumeAtPriceV2 volumeAtPrice; int priceIndex = -1; // Initial value for searching // Iterate through the levels in the Volume Profile to find the matching price level while (sc.GetVolumeAtPriceDataForStudyProfile(vbpStudyID, profileIndex, ++priceIndex, volumeAtPrice) != 0) { if (volumeAtPrice.PriceInTicks == priceInTicks) { double bidPullingStacking = sc.GetBidMarketDepthStackPullValueAtPrice(currentPrice); double askPullingStacking = sc.GetAskMarketDepthStackPullValueAtPrice(currentPrice); // Buy condition: PullingStacking >= threshold and VolumeAtPrice BidVolume > 0 if (bidPullingStacking >= volumeThreshold && volumeAtPrice.BidVolume > 0) { buyConditionMet = true; } // Sell condition: PullingStacking >= threshold and VolumeAtPrice AskVolume > 0 if (askPullingStacking >= volumeThreshold && volumeAtPrice.AskVolume > 0) { sellConditionMet = true; } break; } } // Execute Buy or Sell based on conditions if (buyConditionMet && currentPosition == 0) { PlaceBracketOrder(sc, tradeInfo, 1, orderQuantity, currentPrice, stopLossTicks, takeProfitTicks); } else if (sellConditionMet && currentPosition == 0) { PlaceBracketOrder(sc, tradeInfo, -1, orderQuantity, currentPrice, 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 && (currentPrice <= stopLossPrice || currentPrice >= takeProfitPrice)) || (tradeInfo.positionType == -1 && (currentPrice >= stopLossPrice || currentPrice <= takeProfitPrice))) { sc.FlattenAndCancelAllOrders(); tradeInfo.tradeEntered = false; tradeInfo.positionType = 0; } else if (!tradeInfo.trailingStopActivated && tradeInfo.stopOrderID > 0 && ((tradeInfo.positionType == 1 && currentPrice >= trailingStopTriggerPrice) || (tradeInfo.positionType == -1 && currentPrice <= 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 && currentPrice >= breakevenPrice) || (tradeInfo.positionType == -1 && currentPrice <= 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; } now to see if it does what it is meant to... |
[2024-08-07 08:41:49] |
User357489 - Posts: 72 |
if its of any help- the study settings that it creates:
|
[2024-08-07 12:29:20] |
User357489 - Posts: 72 |
its definitely not doing what i intended...
|
[2024-08-07 13:37:14] |
User431178 - Posts: 541 |
its definitely not doing what i intended...
Can you elaborate? |
[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
|
To post a message in this thread, you need to log in with your Sierra Chart account: