Apre simultaneamente più ordini a mercato con magic number sequenziali, consentendo la chiusura parziale delle posizioni a diversi target di profitto o stop loss. Ideale per strategie di scaling e per la gestione di livelli di rischio multipli.
Snippet Multiple Orders at Market: invia più ordini contemporaneamente con magic number differenti.
Nello screenshot, seleziona il numero di ordini e un magic number. Se selezioni 3 come numero di ordini e 1000 come magic number, verranno creati 3 ordini a mercato con i seguenti magic number: 1000, 1001 e 1002.
Chiudi parzialmente alcuni ordini a mercato su un target di profitto, quindi chiudi gli altri ordini su target di profitto o stop loss differenti.
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 {}
}