10. 2. 2022

5 3

Orden de mercado múltiple

A continuación se muestra un fragmento de órdenes múltiples en el mercado .

 

Enviará varios pedidos a la vez con un número mágico diferente.

En la captura , puede seleccionar el nb (número) de orden y un número mágico.

 

Por ejemplo, si selecciona 3 como número de órdenes y 1000 como número mágico, se crearán 3 órdenes de mercado con el siguiente número mágico: 1000, 1001 y 1002...

(puede crear tantos pedidos como necesite)

A continuación, puede cerrar parcialmente algunas de las órdenes de mercado en un objetivo de beneficios y luego cerrar otras órdenes en diferentes objetivos de beneficios o 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.lib.SettingsMap;
import com.strategyquant.tradinglib.ATM;
import com.strategyquant.tradinglib.ATMExit;
import com.strategyquant.tradinglib.BlockDefinitionException;
import com.strategyquant.tradinglib.BuildingBlock;
import com.strategyquant.tradinglib.CategoryOrder;
import com.strategyquant.tradinglib.Editor;
import com.strategyquant.tradinglib.Editors;
import com.strategyquant.tradinglib.ExitMethod;
import com.strategyquant.tradinglib.ExitTypes;
import com.strategyquant.tradinglib.Help;
import com.strategyquant.tradinglib.IActionEventListener;
import com.strategyquant.tradinglib.IFormula;
import com.strategyquant.tradinglib.ILiveOrder;
import com.strategyquant.tradinglib.Order;
import com.strategyquant.tradinglib.OrderCloseTypes;
import com.strategyquant.tradinglib.OrderTypes;
import com.strategyquant.tradinglib.Parameter;
import com.strategyquant.tradinglib.Required;
import com.strategyquant.tradinglib.ReturnTypes;
import com.strategyquant.tradinglib.SortOrder;
import com.strategyquant.tradinglib.StrategyBase;
import com.strategyquant.tradinglib.atm.exits.None;
import com.strategyquant.tradinglib.atm.exits.TrailingStop;
import com.strategyquant.tradinglib.simulator.Engines;
import SQ.ExitMethods.StopLoss;
import SQ.Functions.OrderFunctions;
import SQ.Internal.ActionBlock;
import SQ.Internal.MMFormulaBlock;

// Modified in France by Emmanuel Evrard for the StrategyQuantX Community :)
@BuildingBlock(name="(MMKT) Enter Multiple Order at market", display="EnterMultipleOrderAtMarket", returnType=ReturnTypes.Order)
@Help("Opens Multiple order at current market price")
@SortOrder(400)
@CategoryOrder(100)
public class EnterAtMarketMultiOrder extends ActionBlock 
{

    private static final int MaxDistanceFromMarketHash = "MaxDistanceFromMarket.MaxDistanceFromMarket".hashCode();
    private static final int MaxDistanceFromMarketPctHash = "MaxDistanceFromMarket.MaxDistancePct".hashCode();
    
    // Basic parameters
    @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;

    // Other parameters
    @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.")
    @Editor(type=Editors.SelectionVariables)
    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")
    @Editor(type=Editors.SelectionVariables)
    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) 
        {
            // market is not flat and duplicate trades are not allowed
            return;
        }
        
        // open trade
        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();
        
        if(atm != null && atm.isApplicable(Strategy, size, sl, orderType)) 
        {
            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 ;
                openATMOrder(atm, -1, size, sl, pt, orderType, 0);
            }
        } 
        else 
        {
            int MagicNumber1 = MagicNumber;
            for(int i = 0; i < NbOrder; i++) 
            {
                MagicNumber = MagicNumber1 + i ;
                openNormalOrder(-1, size, sl, orderType, 0);
            }
        }
    }

    //------------------------------------------------------------------------

    protected void openATMOrder(ATM atm, double openPrice, double fullSize, double sl, double pt, byte orderType, int barsValid) throws TradingException 
    {
        ExitMethod slExit = getStopLossExit();
        double sizeSoFar = 0;
        
        if(Strategy.getEngine() == Engines.MetaTrader4 || Strategy.getEngine() == Engines.MetaTrader5Hedged) {
            for(int i=0; i<atm.getExitsCount(); i++) {
                ATMExit atmExit = tryCloneATMExit(atm.getExit(i));
            
                boolean isLastExit = (i == atm.getExitsCount()-1);
                double size = atmExit.computeSize(fullSize, sizeSoFar, isLastExit);
                
                if(size > 0) {
                    ILiveOrder order = Strategy.Trader.Open(orderType, Symbol, openPrice)
                            .setSize(size)
                            .setMagicNumber(MagicNumber)
                            .setComment(Comment)
                            .Send();
    
                    sizeSoFar += order.getSize();
                    
                    if(order.isSuccessful()) {
                        handleBarsValid(order, barsValid);
                        
                        // add standard SL
                        if(slExit != null && !order.isClosedOrder()) {
                            slExit.setForOrder(order, Strategy);
                        }
                        
                        // add ATM exit
                        atmExit.setForOrder(order, Strategy, sl, pt);
                    }
                }
            }
        }
        else {
            ILiveOrder order = Strategy.Trader.Open(orderType, Symbol, openPrice)
                    .setSize(fullSize)
                    .setMagicNumber(MagicNumber)
                    .setComment(Comment)
                    .Send();

            if(order.isSuccessful()) {
                handleBarsValid(order, barsValid);
                
                // add standard SL
                if(slExit != null && !order.isClosedOrder()) {
                    slExit.setForOrder(order, Strategy);
                }
                
                for(byte i=0; i<atm.getExitsCount(); i++) {
                    ATMExit atmExit = tryCloneATMExit(atm.getExit(i));
                    boolean isLastExit = (i == atm.getExitsCount() - 1);
                    double size = atmExit.computeSize(fullSize, sizeSoFar, isLastExit);
                    
                    if(size > 0) {
                        sizeSoFar += Strategy.getEngine() == Engines.MetaTrader5Netted ? openNewATMNettingOrder(order, atmExit, size, sl, pt, i) : openNewTSATMOrder(order, atmExit, size, sl, pt, i);
                    }
                }
            }
        }
    }

    //------------------------------------------------------------------------

    private double openNewTSATMOrder(ILiveOrder mainOrder, ATMExit atmExit, double size, double sl, double pt, byte exitIndex) throws TradingException {
        mainOrder.registerEvent(UpdateEventTypes.BarOpen, new IActionEventListener() {
            private ILiveOrder exitOrder = null;
            private double actualSL = -1, actualPT = -1;
            private double lastTS = -1;
            private boolean filled = false;
            
            @Override
            public void OnActionEvent(StrategyBase strategy) throws TradingException {
                if(mainOrder.isClosedOrder()) {
                    if(exitOrder != null) {
                        exitOrder.Close(OrderCloseTypes.Deleted);
                        exitOrder = null;
                    }
                    return;
                }
                
                if(!mainOrder.isMarketOrder()) return;
                
                //SL and PT must be calculated when order is filled. Otherwise it may use old indicator values (TradeStation fills on next bar)
                
                actualSL = computeSL(mainOrder.getOrderType(), mainOrder.getOpenPrice());
                actualPT = computePT(mainOrder.getOrderType(), mainOrder.getOpenPrice());
                
                if(atmExit.exitLevel instanceof None) {
                    None noneExit = (None) atmExit.exitLevel;
                    
                    if(noneExit.checkExitAfterBars(mainOrder)) {
                        noneExit.deactivate();
                        
                        Strategy.Trader.Open(mainOrder.isLong() ? OrderTypes.Sell : OrderTypes.Buy, mainOrder.getSymbol(), 0)
                                .setSize(size)
                                .setMagicNumber(MagicNumber)
                                .setComment(Comment)
                                .setExitIndex(exitIndex)
                                .Send();
                    }
                }
                else if(atmExit.exitLevel instanceof TrailingStop) {		
                    if(filled) return;
                    
                    double newTrailingPrice = SQUtils.fixPrice(Strategy.getInstrumentInfo().tickStep, atmExit.exitLevel.getNettingPrice(Strategy, mainOrder, actualSL, actualPT));
                    
                    if(mainOrder.isLong()) {
                        if(newTrailingPrice > mainOrder.getOpenPrice() && newTrailingPrice > actualSL && newTrailingPrice > lastTS) {
                            //move trailing exit closer to current price
                            lastTS = newTrailingPrice;
                        }
                    }
                    else {
                        if(newTrailingPrice < mainOrder.getOpenPrice() && newTrailingPrice < actualSL && (newTrailingPrice < lastTS || lastTS < 0)) {
                            //move trailing exit closer to current price
                            lastTS = newTrailingPrice;
                        }
                    }

                    if(exitOrder != null) {
                        if(exitWasFilled(exitOrder)) {	//Trailing stop has been hit
                            filled = true;
                            return;		
                        }
                        else {
                            exitOrder.Close(OrderCloseTypes.Replaced);
                        }
                    }
                    
                    if(lastTS > 0) {
                        exitOrder = Strategy.Trader.Open(Direction > 0 ? OrderTypes.SellStop : OrderTypes.BuyStop, Symbol, lastTS)
                            .setSize(size)
                            .setMagicNumber(MagicNumber)
                            .setComment(Comment)
                            .setExitIndex(exitIndex)
                            .Send();

                        exitOrder.registerEvent(UpdateEventTypes.OrderFilled, new IActionEventListener() {
                            @Override
                            public void OnActionEvent(StrategyBase Strategy) throws TradingException {
                                if(exitWasFilled(exitOrder)) {
                                    filled = true;
                                }
                            }
                        });
                    }
                }
                else {
                    if(filled) return;
                    
                    double exitOpenPrice = SQUtils.fixPrice(Strategy.getInstrumentInfo().tickStep, atmExit.exitLevel.getNettingPrice(Strategy, mainOrder, actualSL, actualPT));

                    if(exitOpenPrice <= 0) {
                        return;
                    }
                    
                    if(exitOrder != null) {
                        if(exitWasFilled(exitOrder)) return;
                        else {
                            exitOrder.Close(OrderCloseTypes.Deleted);
                            exitOrder = null;
                        }
                    }
                    
                    exitOrder = Strategy.Trader.Open(Direction > 0 ? OrderTypes.SellLimit : OrderTypes.BuyLimit, Symbol, exitOpenPrice)
                            .setSize(size)
                            .setMagicNumber(MagicNumber)
                            .setComment(Comment)
                            .setExitIndex(exitIndex)
                            .Send();
                    
                    if(exitOrder.isSuccessful()) {
                        exitOrder.registerEvent(UpdateEventTypes.BarOpen, new IActionEventListener() {
                            @Override
                            public void OnActionEvent(StrategyBase strategy) throws TradingException {
                                boolean mainOrderExists = false;
                                
                                for(int i=Strategy.Trader.getOpenOrdersCount(false) - 1; i >= 0; i--) {
                                    ILiveOrder order = Strategy.Trader.getOpenOrder(i, false);
                                    
                                    if(order.getOrderId() == mainOrder.getOrderId()) {
                                        mainOrderExists = true;
                                    }
                                }
                                
                                if(!mainOrderExists) {
                                    exitOrder.Close(OrderCloseTypes.Deleted);
                                }
                            }
                        });	
                        exitOrder.registerEvent(UpdateEventTypes.OrderFilled, new IActionEventListener() {
                            @Override
                            public void OnActionEvent(StrategyBase Strategy) throws TradingException {
                                if(exitWasFilled(exitOrder)) {
                                    filled = true;
                                }
                            }
                        });
                    }
                }
            }
        });	
        
        return size;
    }
    
    //------------------------------------------------------------------------

    private double openNewATMNettingOrder(ILiveOrder mainOrder, ATMExit atmExit, double size, double sl, double pt, byte exitIndex) throws TradingException {
        // for None attach a BarOpen event listener and close after number of bars set
        
        if(atmExit.exitLevel instanceof None) {
            mainOrder.registerEvent(UpdateEventTypes.BarOpen, new IActionEventListener() {
                @Override
                public void OnActionEvent(StrategyBase strategy) throws TradingException {
                    if(mainOrder.isClosedOrder() || !mainOrder.isMarketOrder()) return;
                    
                    None noneExit = (None) atmExit.exitLevel;
                    
                    if(noneExit.checkExitAfterBars(mainOrder)) {
                        noneExit.deactivate();
                        
                        ILiveOrder exitOrder = Strategy.Trader.Open(mainOrder.isLong() ? OrderTypes.Sell : OrderTypes.Buy, mainOrder.getSymbol(), 0)
                                .setSize(size)
                                .setMagicNumber(MagicNumber)
                                .setComment(Comment)
                                .setExitIndex(exitIndex)
                                .Send();
                    }
                }
            });	
            
            return size;
        }
        else if(atmExit.exitLevel instanceof TrailingStop) {
            mainOrder.registerEvent(UpdateEventTypes.BarOpen, new IActionEventListener() {
                private ILiveOrder exitOrder = null;
                private double lastTS = -1;
                private boolean filled = false;
                
                @Override
                public void OnActionEvent(StrategyBase strategy) throws TradingException {
                    if(filled) return;
                    
                    if(mainOrder.isClosedOrder()) {
                        if(exitOrder != null) {
                            exitOrder.Close(OrderCloseTypes.Deleted);
                            exitOrder = null;
                        }
                        return;
                    }
                    
                    if(mainOrder.isMarketOrder()) {
                        double newTrailingPrice = SQUtils.fixPrice(Strategy.getInstrumentInfo().tickStep, atmExit.exitLevel.getNettingPrice(Strategy, mainOrder, mainOrder.getSL(), mainOrder.getPT()));
                        double prevTS = lastTS;
                        
                        if(mainOrder.isLong()) {
                            if(newTrailingPrice > mainOrder.getOpenPrice() && newTrailingPrice > mainOrder.getSL() && newTrailingPrice > lastTS) {
                                //move trailing exit closer to current price
                                lastTS = newTrailingPrice;
                            }
                        }
                        else {
                            if(newTrailingPrice < mainOrder.getOpenPrice() && newTrailingPrice < mainOrder.getSL() && (newTrailingPrice < lastTS || lastTS < 0)) {
                                //move trailing exit closer to current price
                                lastTS = newTrailingPrice;
                            }
                        }
                        
                        if(prevTS != lastTS && lastTS > 0) {
                            if(exitOrder != null) {
                                exitOrder.Close(OrderCloseTypes.Replaced);
                            }
                            
                            exitOrder = Strategy.Trader.Open(Direction > 0 ? OrderTypes.SellStop : OrderTypes.BuyStop, Symbol, lastTS)
                                .setSize(size)
                                .setMagicNumber(MagicNumber)
                                .setComment(Comment)
                                .setExitIndex(exitIndex)
                                .Send();
                            
                            exitOrder.registerEvent(UpdateEventTypes.OrderFilled, new IActionEventListener() {
                                @Override
                                public void OnActionEvent(StrategyBase Strategy) throws TradingException {
                                    if(exitWasFilled(exitOrder)) {
                                        filled = true;
                                    }
                                }
                            });
                        }
                    }
                }
            });	

            return size;
        }
        
        // for other types create limit orders
        
        double exitOpenPrice = SQUtils.fixPrice(Strategy.getInstrumentInfo().tickStep, atmExit.exitLevel.getNettingPrice(Strategy, mainOrder, sl, pt));

        if(exitOpenPrice <= 0) {
            return 0;
        }
        
        ILiveOrder exitOrder = Strategy.Trader.Open(Direction > 0 ? OrderTypes.SellLimit : OrderTypes.BuyLimit, Symbol, exitOpenPrice)
                .setSize(size)
                .setMagicNumber(MagicNumber)
                .setComment(Comment)
                .setExitIndex(exitIndex)
                .Send();
        
        if(exitOrder.isSuccessful()) {
            exitOrder.registerEvent(UpdateEventTypes.BarOpen, new IActionEventListener() {
                @Override
                public void OnActionEvent(StrategyBase strategy) throws TradingException {
                    boolean mainOrderExists = false;
                    
                    for(int i=Strategy.Trader.getOpenOrdersCount(false) - 1; i >= 0; i--) {
                        ILiveOrder order = Strategy.Trader.getOpenOrder(i, false);
                        
                        if(order.getOrderId() == mainOrder.getOrderId()) {
                            mainOrderExists = true;
                        }
                    }
                    
                    if(!mainOrderExists) {
                        exitOrder.Close(OrderCloseTypes.Deleted);
                    }
                }
            });	
            
            return size;
        }
        else return 0;
    }

    //------------------------------------------------------------------------

    private boolean exitWasFilled(ILiveOrder exitOrder) {
        return exitOrder.isMarketOrder() && exitOrder.getCloseTime() > 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()) {
                    if(AllowDuplicateTrades) {
                        //we have to clone the exit method, otherwise it makes problems when strategy has duplicate trades enabled (problem example: Trailing Stop is set only for the first order)
                        try {
                            ExitMethod exitMethodCloned = (ExitMethod) exitMethod.clone(true, Strategy);
                            exitMethodCloned.setForOrder(order, Strategy);
                        } 
                        catch (BlockDefinitionException e) {
                            Log.error("Cannot clone exit method '" + exitMethod.getClass().getName() + "' for order #" + order.getOrderId(), e);
                        }
                    }
                    else {
                        exitMethod.setForOrder(order, Strategy);
                    }
                }
            }
        }
    }

    //------------------------------------------------------------------------

    protected void handleBarsValid(ILiveOrder order, int barsValid) throws TradingException {
        if(order.isClosedOrder() || order.isMarketOrder()) return;
        
        // order is placed, now handle order validity
        if(barsValid != 0) {
            order.registerEvent(UpdateEventTypes.BarOpen, new IActionEventListener() {
                @Override
                public void OnActionEvent(StrategyBase strategy) throws TradingException {
                    checkBarsValid(order, barsValid);
                }
            });
        }
    }
    

    //------------------------------------------------------------------------

    protected void checkBarsValid(ILiveOrder order, int barsValid) throws TradingException {
        if(order.isClosedOrder()) return;
        
        if(order.isPendingOrder() && order.getBarsInTrade() >= barsValid) {
            order.Close(OrderCloseTypes.Expired);
        }
    }
    
    //------------------------------------------------------------------------

    protected double computeSL(byte orderType, double orderPrice) throws TradingException {
        ExitMethod slExit = getStopLossExit();
        
        if(slExit == null) {
            // no SL
            return Order.NOT_DEFINED;
        }
        
        return SQUtils.fixPrice(Strategy.getInstrumentInfo().tickStep, slExit.computeValue(orderType, Strategy, Symbol, orderPrice));
    }
    

    //------------------------------------------------------------------------

    protected double computePT(byte orderType, double orderPrice) throws TradingException {
        ExitMethod ptExit = getProfitTargetExit();
        
        if(ptExit == null) {
            // no PT
            return Order.NOT_DEFINED;
        }

        double tickStep = Strategy.getInstrumentInfo().tickStep;
        return SQUtils.fixPrice(tickStep, ptExit.computeValue(orderType, Strategy, Symbol, orderPrice));
    }
    
    //------------------------------------------------------------------------

    private ExitMethod getStopLossExit() {
        ExitMethod slExit = null;
        
        for(ExitMethod exitMethod : ExitMethods) {
            if(exitMethod.getExitType() == ExitTypes.StopLoss) {
                slExit = exitMethod;
                break;
            }
        }
        
        return slExit;
    }
    
    //------------------------------------------------------------------------

    private ExitMethod getProfitTargetExit() {
        ExitMethod ptExit = null;
        
        for(ExitMethod exitMethod : ExitMethods) {
            if(exitMethod.getExitType() == ExitTypes.ProfitTarget) {
                ptExit = exitMethod;
                break;
            }
        }
        
        return ptExit;
    }
    
    //------------------------------------------------------------------------

    protected double computeSize(byte orderType, double price, double sl) throws TradingException {
        MMFormulaBlock sizeFormula = (MMFormulaBlock) Size;
        
        return sizeFormula.computeSize(Strategy, Symbol, orderType, price, sl);
    }

    //------------------------------------------------------------------------

    protected ILiveOrder checkLiveOrderExists(int direction, boolean includeClosingOrders) {
        int count = Strategy.Trader.getOpenOrdersCount(includeClosingOrders) - 1;
        
        for(int i=count; i >= 0; i--) {
            ILiveOrder order = Strategy.Trader.getOpenOrder(i, includeClosingOrders);
            
            if(OrderFunctions.identify(order, Strategy, Symbol, direction, MagicNumber, Comment) && order.isMarketOrder()) {
                return order;
            }
        }
        
        return null;
    }
    
    //------------------------------------------------------------------------

    /** 
     * this method is called only in Tradestation engine, to handle exits (SL, PT, etc.) as same as they are handled in TS.
     * @throws TradingException 
     */
    public void OnApplyExits() throws TradingException {
        ArrayList<ILiveOrder> orders = getOpenOrders(Direction);
        ATM atm = Strategy.getATM();
        
        boolean slPlaced = false;
        if(orders != null) {
            for(int i=0; i<orders.size(); i++) {
                ILiveOrder order = orders.get(i);
                boolean atmUsed = atm != null && atm.isApplicable(Strategy, order.getSize(), order.getSL(), order.getOrderType());
                
                for(ExitMethod exitMethod : ExitMethods) {
                    if(!atmUsed || exitMethod instanceof StopLoss) {
                        if(exitMethod.setExit(order, Strategy)) {
                            slPlaced = true;
                        }
                    }
                }
                
                if(!slPlaced && order.getSL() != Order.NOT_DEFINED) {
                    // we have to set SL from order - handling if there is no SL, only for Trailing stop or Move2BE
                    int direction = order.isLong() ? -1 : 1;

                    byte orderType = (direction > 0 ? OrderTypes.BuyToCoverStop : OrderTypes.SellToCoverStop);

                    ILiveOrder slOrder = Strategy.Trader.Open(orderType, order.getSymbol(), order.getSL())
                            .setComment("SL")
                            .setMagicNumber(order.getMagicNumber())
                            .Send();
                }
            }
        }
    }

    //------------------------------------------------------------------------

    private ArrayList<ILiveOrder> getOpenOrders(int direction) {
        ArrayList<ILiveOrder> orders = null;
        
        for(int i=0; i<Strategy.Trader.getOpenOrdersCount(false); i++) {
            ILiveOrder order = Strategy.Trader.getOpenOrder(i, false);
            
            if(order.isPendingOrder()) {
                continue;
            }
            
            if(OrderFunctions.identify(order, Strategy, Symbol, direction, MagicNumber, Comment) && order.isMarketOrder()) {
                if(orders == null) {
                    orders = new ArrayList<ILiveOrder>();
                }
                
                orders.add(order);
            }
        }
        
        return orders;
    }

    //------------------------------------------------------------------------

    protected boolean engineSupportsDuplicateTrades() {
        return Strategy.Trader.supportsDuplicateTrades();
    }

    //------------------------------------------------------------------------

    private ATMExit tryCloneATMExit(ATMExit exit) throws TradingException {
        ATMExit clone = exit.clone();
        if(clone == null) {
            throw new TradingException("Unable to create ATMExit object");
        }
        
        return clone;
    }

    //------------------------------------------------------------------------

    protected boolean checkOpenPriceWithinRange(double openPrice) {
        try {
            SettingsMap settings = Strategy.getSettings();
            if(settings.containsKey(MaxDistanceFromMarketHash) && settings.containsKey(MaxDistanceFromMarketPctHash) && ((boolean) settings.get(MaxDistanceFromMarketHash))) {
                double maxPctDistance = SQUtils.round2((double) settings.get(MaxDistanceFromMarketPctHash));
                double currentPrice = Direction > 0 ? Strategy.MarketData.Chart(Symbol).Ask() : Strategy.MarketData.Chart(Symbol).Bid();
                
                double distancePct = SQUtils.round2(Math.abs(currentPrice - openPrice) / currentPrice * 100);
                if(distancePct > maxPctDistance) {
                    Log.debug("Order skipped - too far from market. Open price: {}, Market price: {}, Max distance: {}%", openPrice, currentPrice, maxPctDistance);
                    return false;
                }
            }
        }
        catch(Throwable t) {
            Log.error("Error while checking open price max distance", t);
        }
        
        return true;
    }
    
}

 

 

Suscríbase a
Notificar a
3 Comentarios
Más antiguo
Más reciente Más votados
Feedbacks de Inline
Ver todos los comentarios
bentra
10. 2. 2022 9:02 pm

¡Buen trabajo!

hamed rahmatpour
hamed rahmatpour
9. 2. 2024 12:49 pm

Hola,
could you guide me how can i add this code to the exsisting strategy?