Opens multiple market orders simultaneously with sequential magic numbers, enabling partial position closure at different profit targets or stop losses. Ideal for scaling strategies and managing multiple risk levels.
Multiple Orders at Market snippet - sends multiple orders at once with different magic numbers.
On the capture, select the nb (number) of orders and a magic number. If you select 3 as number of orders and 1000 as magic number, it will create 3 market orders with magic numbers: 1000, 1001, then 1002.
Close partially some market orders on one profit target then close other orders on different profit targets or stop loss.
package SQ.Blocks.Order.Open;
import java.util.ArrayList;
import com.strategyquant.datalib.TradingException;
import com.strategyquant.datalib.UpdateEventTypes;
import com.strategyquant.lib.SQTime;
import com.strategyquant.lib.SQUtils;
import com.strategyquant.tradinglib.*;
// Modified by Emmanuel Evrard for StrategyQuantX Community
@BuildingBlock(name="(MMKT) Enter Multiple Order at market", display="EnterMultipleOrderAtMarket", returnType=ReturnTypes.Order)
@Help("Opens Multiple order at current market price")
public class EnterAtMarketMultiOrder extends ActionBlock
{
@Parameter(defaultValue="Any", category="Basic", showIfDefault=false)
@Editor(type=Editors.SelectionSymbolsWithAny)
public String Symbol;
@Parameter(defaultValue="1", category="Basic")
@Editor(type=Editors.Selection, values="Long=1,Short=-1")
public int Direction;
@Parameter(category="Basic")
@Editor(type=Editors.Formula, formulaName="Size")
@Required
public IFormula Size;
@Parameter(defaultValue="MagicNumber", category="Order identification", showIfDefault=false)
@Help("Magic number is used to identify the first trade, it should be unique for every trade you open.")
public int MagicNumber;
@Parameter(defaultValue="Number Of Order", category="Order identification", showIfDefault=false)
@Help("Number Of Order is used to set the quantity of order, Their MagicNumbers are successives to the above MagicNumber")
public int NbOrder;
@Parameter(defaultValue="", category="Order identification", showIfDefault=false)
public String Comment;
@Parameter(defaultValue="false", category="Order identification", showIfDefault=false)
@Help("If set to true, it will allow to place multiple trades with the same Magic Number")
public boolean AllowDuplicateTrades;
public ExitMethod[] ExitMethods;
@Override
public void OnAction() throws TradingException
{
if((!AllowDuplicateTrades || !engineSupportsDuplicateTrades()) && checkLiveOrderExists(0, true) != null)
return;
byte orderType = (Direction > 0 ? OrderTypes.Buy : OrderTypes.Sell);
double sl = computeSL(orderType, (Direction > 0 ? Strategy.MarketData.Chart(Symbol).Ask() : Strategy.MarketData.Chart(Symbol).Bid()));
double size = computeSize(orderType, 0, sl);
ATM atm = Strategy.getATM();
double pt = computePT(orderType, (Direction > 0 ? Strategy.MarketData.Chart(Symbol).Ask() : Strategy.MarketData.Chart(Symbol).Bid()));
int MagicNumber1 = MagicNumber;
for(int i = 0; i < NbOrder; i++)
{
MagicNumber = MagicNumber1 + i;
if(atm != null && atm.isApplicable(Strategy, size, sl, orderType)) {
openATMOrder(atm, -1, size, sl, pt, orderType, 0);
} else {
openNormalOrder(-1, size, sl, orderType, 0);
}
}
}
protected void openNormalOrder(double openPrice, double size, double sl, byte orderType, int barsValid) throws TradingException {
ILiveOrder order = Strategy.Trader.Open(orderType, Symbol, openPrice)
.setSize(size).setMagicNumber(MagicNumber).setComment(Comment).Send();
if(order.isSuccessful()) {
handleBarsValid(order, barsValid);
for(ExitMethod exitMethod : ExitMethods) {
if(!order.isClosedOrder()) exitMethod.setForOrder(order, Strategy);
}
}
}
protected double computeSL(byte orderType, double orderPrice) throws TradingException {
ExitMethod slExit = getStopLossExit();
return slExit == null ? Order.NOT_DEFINED : SQUtils.fixPrice(Strategy.getInstrumentInfo().tickStep, slExit.computeValue(orderType, Strategy, Symbol, orderPrice));
}
protected double computePT(byte orderType, double orderPrice) throws TradingException {
ExitMethod ptExit = getProfitTargetExit();
return ptExit == null ? Order.NOT_DEFINED : SQUtils.fixPrice(Strategy.getInstrumentInfo().tickStep, ptExit.computeValue(orderType, Strategy, Symbol, orderPrice));
}
private ExitMethod getStopLossExit() {
for(ExitMethod e : ExitMethods) if(e.getExitType() == ExitTypes.StopLoss) return e;
return null;
}
private ExitMethod getProfitTargetExit() {
for(ExitMethod e : ExitMethods) if(e.getExitType() == ExitTypes.ProfitTarget) return e;
return null;
}
protected double computeSize(byte orderType, double price, double sl) throws TradingException {
return ((MMFormulaBlock) Size).computeSize(Strategy, Symbol, orderType, price, sl);
}
protected ILiveOrder checkLiveOrderExists(int direction, boolean includeClosingOrders) {
for(int i=Strategy.Trader.getOpenOrdersCount(includeClosingOrders)-1; i>=0; i--) {
ILiveOrder order = Strategy.Trader.getOpenOrder(i, includeClosingOrders);
if(order.isMarketOrder() && OrderFunctions.identify(order, Strategy, Symbol, direction, MagicNumber, Comment))
return order;
}
return null;
}
protected boolean engineSupportsDuplicateTrades() { return Strategy.Trader.supportsDuplicateTrades(); }
protected void handleBarsValid(ILiveOrder order, int barsValid) throws TradingException {}
}