Bot Code Example

From SharpTrader Arbitrage Software Wiki: A Detailed Overview of High-Speed Trading Technology
Revision as of 17:33, 10 April 2026 by Admin (talk | contribs) (Auto-create translation (about))
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
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 = "";

}

}

}

}