using System;
using System.Linq;
using cAlgo.API;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
using cAlgo.Indicators;
namespace cAlgo
{
[Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.FullAccess)]
public class SMATriggerRobot : Robot
{
[Parameter("SMA Period", DefaultValue = 200)]
public int SMAPeriod { get; set; }
private DateTime _startTime;
private DateTime _stopTime;
[Parameter("Start Hour", DefaultValue = 10.0)]
public double StartTime { get; set; }
[Parameter("Stop Hour", DefaultValue = 12.0)]
public double StopTime { get; set; }
[Parameter()]
public DataSeries SourceSeries { get; set; }
[Parameter("Break-Even Trigger (pips)", DefaultValue = 10)]
public double BreakEvenTrigger { get; set; }
[Parameter("Period SMA #2", DefaultValue = 50, MinValue = 1, MaxValue =
100)]
public int PeriodsSma2 { get; set; }
[Parameter("Period SMA #3", DefaultValue = 20, MinValue = 1, MaxValue =
100)]
public int PeriodsSma3 { get; set; }
[Parameter("Source SMA #2")]
public DataSeries SourceSma2 { get; set; }
[Parameter("Source SMA #3")]
public DataSeries SourceSma3 { get; set; }
private bool lastCandleAboveSMA50 = false;
private bool lastCandleBelowSMA50 = false;
[Parameter("Include Trailing Stop", DefaultValue = false)]
public bool IncludeTrailingStop { get; set; }
[Parameter("Trailing Stop Trigger (pips)", DefaultValue = 10)]
public double TrailingStopTrigger { get; set; }
[Parameter("Trailing Stop Steps (pips)", DefaultValue = 10)]
public double TrailingStopSteps { get; set; }
[Parameter("Profit Target (pips)", DefaultValue = 50)]
public double ProfitTarget { get; set; }
[Parameter("Pips Offset", DefaultValue = 20)]
public double PipsOffset { get; set; }
[Parameter("EMA Period", DefaultValue = 50)]
public int EMAPeriod { get; set; }
[Parameter("Lot Size", DefaultValue = 0.1)]
public double LotSize { get; set; }
public string InstanceName { get; set; }
[Parameter("Take Profit", Group = "Protection", DefaultValue = 1)]
public int TakeProfit { get; set; }
[Parameter("Stop Loss", Group = "Protection", DefaultValue = 0)]
public int StopLoss { get; set; }
[Parameter("Percentage to Close", DefaultValue = 0.5, MinValue = 0.0,
MaxValue = 1.0, Step = 0.01)]
public double PercentageToClose { get; set; }
[Parameter("Minimum Profit to Trigger Partial Close (pips)", DefaultValue =
50, MinValue = 1)]
public double MinProfitToTriggerPartialClose { get; set; }
[Parameter("Number distance", DefaultValue = 5, MinValue = 5, MaxValue=
1000 )]
public double Numberdistance { get; set; }
[Parameter("Periods", DefaultValue = 14)]
public int Periods { get; set; }
[Parameter("Source")]
public DataSeries Source { get; set; }
private MovingAverage sma;
private RelativeStrengthIndex rsi;
private SimpleMovingAverage _sma2 { get; set; }
private SimpleMovingAverage _sma3 { get; set; }
private ExponentialMovingAverage ema;
private bool isBuyStopOrderPlaced = false;
private bool isSellStopOrderPlaced = false;
protected override void OnStart()
{
// Start Time is the same day at 22:00:00 Server Time
_startTime = Server.Time.Date.AddHours(StartTime);
// Stop Time is the next day at 06:00:00
_stopTime = Server.Time.Date.AddHours(StopTime);
Print("Start Time {0},", _startTime);
Print("Stop Time {0},", _stopTime);
// Initialize the SMA indicator
sma = Indicators.SimpleMovingAverage(MarketSeries.Close, SMAPeriod);
_sma2 = Indicators.SimpleMovingAverage(SourceSeries, 50);
_sma3 = Indicators.SimpleMovingAverage(SourceSeries, 20);
ema = Indicators.ExponentialMovingAverage(MarketSeries.Close,
EMAPeriod);
rsi= Indicators.RelativeStrengthIndex(Source, Periods);
protected override void OnBar()
{
if (Trade.IsExecuting) return;
var currentHours = Server.Time.TimeOfDay.TotalHours;
bool tradeTime = StartTime < StopTime
? currentHours > StartTime && currentHours < StopTime
: currentHours < StopTime || currentHours > StartTime;
if (!tradeTime)
return;
// Calculate SMA values
double sma200Value = sma.Result.LastValue;
double sma50Value = _sma2.Result.LastValue;
double sma20Value = _sma3.Result.LastValue;
// Calculate RSI value
double rsiValue = rsi.Result.LastValue;
// Calculate the difference in pips between SMA200 and SMA50
double pipsDifference = (sma200Value - sma50Value) / Symbol.PipSize;
// Check if the difference is greater than 700 pips
if (Math.Abs(pipsDifference) >= Numberdistance)
{
// Clear any existing pending orders and return
foreach (var pendingOrder in PendingOrders)
{
CancelPendingOrder(pendingOrder);
}
return;
}
foreach (var position in Positions)
{
double pipsInProfit = CalculatePipsInProfit(position);
// Close partial position if conditions are met
if (pipsInProfit >= MinProfitToTriggerPartialClose)
{
ClosePartialPosition(position, PercentageToClose);
// Move stop loss to breakeven
if (BreakEvenTrigger > 0)
{
double breakEvenPrice = CalculateBreakEvenPrice(position);
ModifyPosition(position, breakEvenPrice,
position.TakeProfit);
}
}
// Trailing stop logic
if (IncludeTrailingStop)
{
double stopLossPrice = position.StopLoss ?? 0.0;
if (position.TradeType == TradeType.Buy)
{
double trailingStopPrice = MarketSeries.High.LastValue -
TrailingStopSteps * Symbol.PipSize;
if (trailingStopPrice > stopLossPrice &&
MarketSeries.High.LastValue > position.EntryPrice + TrailingStopTrigger *
Symbol.PipSize)
{
ModifyPosition(position, trailingStopPrice,
position.TakeProfit);
}
}
else if (position.TradeType == TradeType.Sell)
{
double trailingStopPrice = MarketSeries.Low.LastValue +
TrailingStopSteps * Symbol.PipSize;
if (trailingStopPrice < stopLossPrice &&
MarketSeries.Low.LastValue < position.EntryPrice - TrailingStopTrigger *
Symbol.PipSize)
{
ModifyPosition(position, trailingStopPrice,
position.TakeProfit);
}
}
/*/ Close half of the buy position and open a sell position when SMA20
crosses below SMA50
// Calculate the number of open buy and sell positions
int openBuyPositions = 0;
int openSellPositions = 0;
if (openSellPositions <= 0 && position.TradeType == TradeType.Buy &&
sma20Value < sma50Value)
{
double halfVolume = position.Volume * 0.5;
ClosePosition(position, halfVolume); // Close half of the buy position
double sellVolume = halfVolume * 8.0; // Double the original volume
ExecuteMarketOrder(TradeType.Sell, Symbol, sellVolume,
"SellOnSMA20Cross", StopLoss, 2); // Set TakeProfit to 10 pips
}
// Close half of the sell position and open a buy position when SMA20
crosses above SMA50
else if (openBuyPositions <= 0 &&position.TradeType == TradeType.Sell &&
sma20Value > sma50Value)
{
double halfVolume = position.Volume * 0.5;
ClosePosition(position, halfVolume); // Close half of the sell
position
double buyVolume = halfVolume * 8.0; // Double the original volume
ExecuteMarketOrder(TradeType.Buy, Symbol, buyVolume, "BuyOnSMA20Cross",
StopLoss, 2); // Set TakeProfit to 10 pips
}*/
}
}
// Check for buy conditions
if (MarketSeries.Close.Last(0) > sma200Value && rsiValue > 70)
{
// Place buy order if not already placed
if (Positions.Count <= 0)
{
// Place buy market order
long volume = Symbol.QuantityToVolume(LotSize);
//long volume = Symbol.QuantityToVolume(Account.Balance/10000);
ExecuteMarketOrder(TradeType.Buy, Symbol, volume, "BuyOrder",
StopLoss, TakeProfit);
}
}
else if (sma50Value > sma200Value && MarketSeries.Low.Last(1) <
sma50Value && MarketSeries.Close.Last(0) > sma50Value)
{
// Place buy order on pull-back to SMA50
if (Positions.Count <= 0)
{
// Place buy market order
long volume = Symbol.QuantityToVolume(LotSize);
//long volume = Symbol.QuantityToVolume(Account.Balance/10000);
double entryPrice = Symbol.Ask + PipsOffset * Symbol.PipSize;
DateTime expiration = Server.Time.AddMinutes(5); // Adjust expiration
time as needed
PlaceStopOrder(TradeType.Buy, Symbol, volume, entryPrice, InstanceName,
StopLoss, TakeProfit, expiration);
}
}
// Check for sell conditions
if (MarketSeries.Close.Last(0) < sma200Value && rsiValue < 30)
{
// Place sell order if not already placed
if (Positions.Count <= 0)
{
// Place sell market order
long volume = Symbol.QuantityToVolume(LotSize);
//long volume = Symbol.QuantityToVolume(Account.Balance/10000);
ExecuteMarketOrder(TradeType.Sell, Symbol, volume, "SellOrder",
StopLoss, TakeProfit);
}
}
else if (sma50Value < sma200Value && MarketSeries.High.Last(1) >
sma50Value && MarketSeries.Close.Last(0) < sma50Value)
{
// Place sell order on pull-back to SMA50
if (Positions.Count <= 0)
{
long volume = Symbol.QuantityToVolume(LotSize);
//long volume = Symbol.QuantityToVolume(Account.Balance/10000);
double entryPrice = Symbol.Bid - PipsOffset * Symbol.PipSize;
DateTime expiration = Server.Time.AddMinutes(5); // Adjust expiration
time as needed
PlaceStopOrder(TradeType.Sell, Symbol, volume, entryPrice,
InstanceName, StopLoss, TakeProfit, expiration);
}
}
}
private double CalculateBreakEvenPrice(Position position)
{
double entryPrice = position.EntryPrice;
double symbolPointValue = Symbol.PipValue;
double breakEvenPrice;
if (position.TradeType == TradeType.Buy)
{
breakEvenPrice = entryPrice + BreakEvenTrigger * symbolPointValue;
}
else if (position.TradeType == TradeType.Sell)
{
breakEvenPrice = entryPrice - BreakEvenTrigger * symbolPointValue;
}
else
{
breakEvenPrice = entryPrice;
}
return breakEvenPrice;
}
private double CalculatePipsInProfit(Position position)
{
if (position.TradeType == TradeType.Buy)
{
return (Symbol.Bid - position.EntryPrice) / Symbol.PipSize;
}
else if (position.TradeType == TradeType.Sell)
{
return (position.EntryPrice - Symbol.Ask) / Symbol.PipSize;
}
return 0.0;
}
private void ClosePartialPosition(Position position, double percentage)
{
if (percentage <= 0 || percentage > 1)
{
Print("Invalid percentage value.");
return;
}
double quantityToClose = position.Volume * percentage;
TradeResult result = ClosePosition(position, quantityToClose);
double pipsInProfit = CalculatePipsInProfit(position);
Print($"Pips in Profit: {pipsInProfit}");
if (pipsInProfit >= MinProfitToTriggerPartialClose)
if (result.IsSuccessful)
{
Print($"Closed {percentage:P0} of position. Quantity closed:
{quantityToClose}");
}
else
{
Print("Failed to close position.");
}
}
}
}