Bot Code Example

From SharpTrader Arbitrage Software Wiki: A Detailed Overview of High-Speed Trading Technology
Jump to navigation Jump to search

MACD Bot Example

using System;

using System.Collections.Generic;

using Skender.Stock.Indicators;

using System.Linq;

using SharpTraderBot;

namespace SharpTraderArb.Strategies

{

    public class MACDBot: Bot

    {

        //input parameters

        [PropertyInfo("EURUSD", "Trading symbol")]       

        public string Symbol {get;set;} = "EURUSD";

        [PropertyInfo(TimeFrame.M30, "Timeframe")]       

        public TimeFrame Period {get;set;} =  TimeFrame.M30;

        [PropertyInfo(50, "Take profit")]       

        public double TakeProfit {get;set;} = 50;

        [PropertyInfo(0.1, "Lot size")]               

        public double Lots {get;set;} = 0.1;

        [PropertyInfo(30, "Trailing stop")]               

        public double TrailingStop {get;set;} = 30;

        [PropertyInfo(3, "MACD open level")]                       

        public double MACDOpenLevel {get;set;} = 3;

        [PropertyInfo(2, "MACD close level")]               

        public double MACDCloseLevel {get;set;} = 2;

        [PropertyInfo(30, "Moving average period")]                       

        public int    MATrendPeriod {get;set;} = 26;

       

        //internal variables

        string positionID = "";

        double pointValue = 1e-5;

        double bid,ask;

        string clienOrderId = "";  

        public override void OnInit()

        {

            pointValue = ticker.getPointValue(0, Symbol);

            //check for opened position

            STPosition buyPosition  = getPositionByComment("MACD_buy", 0);

           

            if (buyPosition != null)

               positionID = buyPosition.PositionId;

            STPosition sellPosition  = getPositionByComment("MACD_sell", 0);

           

            if (sellPosition != null)

               positionID = sellPosition.PositionId;

        }

        public override void OnDeinit()

        {

        }

        public override void OnTick(NewTickEventArgs args)

        {

           if (clienOrderId != "") // order is already processing, exit

              return;

           if (ticker.getSymbolName(0,Symbol) != args.tick.symbol)//tick on another symbol

              return;

           double MacdCurrent,MacdPrevious;

           double SignalCurrent,SignalPrevious;

           double MaCurrent,MaPrevious;

           var MACDmain  = indicators.iMACD(0, Symbol,Period,PriceUsed.Close,MACDMode.Main);

            if (MACDmain == null)

            {  

                stopBot();

                return;

            }

            MacdCurrent = (double)MACDmain[0];

            MacdPrevious = (double)MACDmain[1];

            var MACDsignal  = indicators.iMACD(0, Symbol,Period,PriceUsed.Close,MACDMode.Signal);           

           

            if (MACDsignal == null)   

            {  

                stopBot();

                return;

            }

            SignalCurrent = (double)MACDsignal[0];

            SignalPrevious = (double)MACDsignal[1];

           

            var MA = indicators.iEMA(0,Symbol,Period,PriceUsed.Close,MATrendPeriod);

           

            if (MA == null)   

            {  

                stopBot();

                return;

            }

            MaCurrent = (double)MA[0];

            MaPrevious = (double)MA[1];

           bid = ticker.getBid(0, Symbol);

           ask = ticker.getAsk(0, Symbol);

         

        //writeLog(bid.ToString());

       if(positionID == "")// no opened positions - check for entry condition

       {

             writeLog("Time to buy!");   

             clienOrderId = sendOrder(0,Symbol,Lots, OrderSide.BUY,OrderType.MARKET, ask,"MACD_buy");

             return;

       }

        else // we have opened position

        {

           STPosition position = getPositionByID(positionID);

           if (position == null)// this position is already closed

            {

                positionID = "";             

                return;

            }

 

           if(position.side == OrderSide.BUY)//we have buy position opened

           {

            //setting position take profit value (if not set)

            if (position.takeProfit == 0)

                modifyPositionByID(positionID, position.stopLoss, position.openPrice + TakeProfit * pointValue);

            //--- checking closing conditions

            if(MacdCurrent > 0 && MacdCurrent < SignalCurrent && MacdPrevious > SignalPrevious && MacdCurrent>(MACDCloseLevel * pointValue))

              {

                clienOrderId = closePositionByID(positionID);

                return;   

              }

            //--- perform trailing

            if(TrailingStop > 0)

              {

               if(bid - position.openPrice > pointValue * TrailingStop)

                 {

                  if(position.stopLoss < bid-pointValue * TrailingStop)

                    {

                     modifyPositionByID(positionID, bid-pointValue * TrailingStop, position.takeProfit);

                     return;

                    }

                 }

              }

           }

         else //we have sell position opened

           {

            //setting position take profit value (if not set)

            if (position.takeProfit == 0)

                modifyPositionByID(positionID, position.stopLoss, position.openPrice - TakeProfit * pointValue);

            //--- checking closing conditions

            if(MacdCurrent < 0 && MacdCurrent > SignalCurrent && MacdPrevious < SignalPrevious && Math.Abs(MacdCurrent) > (MACDCloseLevel * pointValue))

              {

               clienOrderId = closePositionByID(positionID);

               return;

              }

            //--- check for trailing stop

            if(TrailingStop > 0)

              {

               if((position.openPrice - ask) > (pointValue * TrailingStop))

                 {

                  if((position.stopLoss > (ask + pointValue * TrailingStop)) || (position.stopLoss == 0))

                    {

                      modifyPositionByID(positionID, ask + pointValue * TrailingStop, position.takeProfit);

                      return;

                    }

                 }

              }

           }

        }

        }

        public override void OnPositionOpened(PositionOpenedEventArgs args)

        {

                writeLog($"Position {args.position.PositionId} was opened");

                clienOrderId = "";

                positionID = args.position.PositionId;

        }

        public override void OnPositionClosed(PositionClosedEventArgs args)

        {

                writeLog($"Position {args.position.PositionId} was closed");

                positionID = "";

                clienOrderId = "";

        }

        public virtual void OnOrderStatusUpdate(STOrder order)

        {

            if (order.clientOrderId == clienOrderId && (order.status == OrderStatus.CANCELED || order.status == OrderStatus.REJECTED))

            {

               writeLog($"Order {clienOrderId} was rejected with reason {order.comment}");

               clienOrderId = "";

            }

        }

    }

}