Description
C-3PO (Unimate) - A simple yet effective short-term trading Breakout Strategy. This Robot serves as a template for your own strategy. make it your Own. Good Luck!
- Easy to use and supervise
- Fully configurable settings
- Customizable SL, TP, Break-Even, Trailing-Stop, and Scale Out Trades
- Built-in money management
using System;
using System.Linq;
using cAlgo.API;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
using cAlgo.Indicators;
namespace cAlgo.Robots
{
[Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class Unimate : Robot
{
[Parameter("Instance Name", DefaultValue = "Trend cBot")]
public string PositionId { get; set; }
[Parameter("Percentage Risk Model?", Group = "Volume", DefaultValue = true)]
public bool volPercentBool { get; set; }
[Parameter("Risk %", Group = "Volume", DefaultValue = 1.5, MinValue = 1, MaxValue = 10)]
public double volPercent { get; set; }
[Parameter("Quantity", Group = "Volume", DefaultValue = 2000, MinValue = 1000, Step = 1000)]
public int volQty { get; set; }
[Parameter("User ATR for Protection?", Group = "Protection", DefaultValue = true)]
public bool ATR_Protection { get; set; }
[Parameter("StopLoss (*ATR)", Group = "Protection", DefaultValue = 2.5, Step = 0.1, MinValue = 0, MaxValue = 100)]
public double StopLoss_ATR { get; set; }
[Parameter("TakeProfit (*ATR)", Group = "Protection", DefaultValue = 10.0, Step = 0.1, MinValue = 0, MaxValue = 100)]
public double TakeProfit_ATR { get; set; }
[Parameter("Stop Loss (pips)", Group = "Protection", DefaultValue = 25, MinValue = 1)]
public int StopLoss_Pips { get; set; }
[Parameter("Take Profit (pips)", Group = "Protection", DefaultValue = 100, MinValue = 1)]
public int TakeProfit_Pips { get; set; }
[Parameter("Use Exit Strategy?", Group = "Protection", DefaultValue = true)]
public bool ExitStrategy { get; set; }
[Parameter("MA (Fast)", Group = "Indicators", DefaultValue = 9)]
public int FastPeriods { get; set; }
[Parameter("MA (Slow)", Group = "Indicators", DefaultValue = 50)]
public int SlowPeriods { get; set; }
[Parameter("MA (Type)", Group = "Indicators")]
public MovingAverageType MAType { get; set; }
[Parameter("MA (Source)", Group = "Indicators")]
public DataSeries SourceSeries { get; set; }
[Parameter("RSI (Periods)", Group = "Indicators", DefaultValue = 9)]
public int Periods { get; set; }
[Parameter("RSI (Source)", Group = "Indicators")]
public DataSeries Source { get; set; }
[Parameter("RSI (OverBought)", Group = "Indicators", DefaultValue = 68, MinValue = 65, MaxValue = 100)]
public double OverBought { get; set; }
[Parameter("RSI (OverSold)", Group = "Indicators", DefaultValue = 32, MinValue = 0, MaxValue = 35)]
public double OverSold { get; set; }
[Parameter("ADX (Period)", Group = "Indicators", DefaultValue = 9)]
public int Period { get; set; }
[Parameter("ADX (Threshold)", Group = "Indicators", DefaultValue = 21)]
public int Threshold { get; set; }
[Parameter("Enabled", Group = "Break Even", DefaultValue = true)]
public bool BreakEvenEnabled { get; set; }
[Parameter("Trigger (*ATR)", Group = "Break Even", DefaultValue = 2.5, Step = 0.1, MinValue = 1, MaxValue = 10)]
public double Trigger_ATR { get; set; }
[Parameter("Trigger Pips", Group = "Break Even", DefaultValue = 25, MinValue = 1)]
public double Trigger_Pips { get; set; }
[Parameter("Add Pips", Group = "Break Even", DefaultValue = 2.0, MinValue = 0.0)]
public double AddPips { get; set; }
[Parameter("OnTick", Group = "Break Even", DefaultValue = false)]
public bool OnTickBreakEvenEnabled { get; set; }
[Parameter("Enabled", Group = "Tralling Stop", DefaultValue = true)]
public bool TrallingStopEnabled { get; set; }
[Parameter("Tralling Stop (*ATR)", Group = "Tralling Stop", DefaultValue = 3.0)]
public int TrallingStop_ATR { get; set; }
[Parameter("Tralling Stop (pips)", Group = "Tralling Stop", DefaultValue = 30.0)]
public int TrallingStop_Pips { get; set; }
[Parameter("OnTick", Group = "Tralling Stop", DefaultValue = false)]
public bool OnTickTrallingStopEnabled { get; set; }
[Parameter("Only Show", Group = "Take Profit", DefaultValue = false)]
public bool onlyShowEnabled = false;
[Parameter("Enabled", Group = "Take Profit 1", DefaultValue = true)]
public bool TakeProfit1Enabled { get; set; }
[Parameter("*ATR", Group = "Take Profit 1", DefaultValue = 2.5)]
public double TakeProfit1_ATR { get; set; }
[Parameter("Pips", Group = "Take Profit 1", DefaultValue = 25)]
public double TakeProfit1_Pips { get; set; }
[Parameter("Volume", Group = "Take Profit 1", DefaultValue = 1000)]
public int TakeProfit1Volume { get; set; }
[Parameter("Enabled", Group = "Take Profit 2", DefaultValue = false)]
public bool TakeProfit2Enabled { get; set; }
[Parameter("*ATR", Group = "Take Profit 2", DefaultValue = 5.0)]
public double TakeProfit2_ATR { get; set; }
[Parameter("Pips", Group = "Take Profit 2", DefaultValue = 50)]
public double TakeProfit2_Pips { get; set; }
[Parameter("Volume", Group = "Take Profit 2", DefaultValue = 1000)]
public int TakeProfit2Volume { get; set; }
[Parameter("Enabled", Group = "Take Profit 3", DefaultValue = false)]
public bool TakeProfit3Enabled { get; set; }
[Parameter("*ATR", Group = "Take Profit 3", DefaultValue = 7.5)]
public double TakeProfit3_ATR { get; set; }
[Parameter("Pips", Group = "Take Profit 3", DefaultValue = 75)]
public double TakeProfit3_Pips { get; set; }
[Parameter("Volume", Group = "Take Profit 3", DefaultValue = 1000)]
public int TakeProfit3Volume { get; set; }
[Parameter("Enabled", Group = "Take Profit 4", DefaultValue = false)]
public bool TakeProfit4Enabled { get; set; }
[Parameter("*ATR", Group = "Take Profit 4", DefaultValue = 10.0)]
public double TakeProfit4_ATR { get; set; }
[Parameter("Pips", Group = "Take Profit 4", DefaultValue = 100)]
public double TakeProfit4_Pips { get; set; }
[Parameter("Volume", Group = "Take Profit 4", DefaultValue = 1000)]
public int TakeProfit4Volume { get; set; }
[Parameter("Max Allowable Spread", Group = "Filter", DefaultValue = 2.0, MinValue = 0.1, MaxValue = 100.0, Step = 0.1)]
public double MaxSpread { get; set; }
[Parameter("Allowable Slippage", Group = "Filter", DefaultValue = 3.0, MinValue = 0.5, Step = 0.1)]
public double Slippage { get; set; }
[Parameter("Comment", Group = "Filter", DefaultValue = "Unimate")]
public string Comment { get; set; }
private AverageTrueRange ATR;
private MovingAverage PAC_hi;
private MovingAverage PAC_low;
private MovingAverage slowMa;
private RelativeStrengthIndex RSI;
private DirectionalMovementSystem _dms;
private TakeProfitLevel[] _levels;
private bool entrar = true;
private SymbolInfo _symbolInfo;
private double SPREAD;
private int VolumeInUnits;
private double Stop_Loss;
private double Take_Profit;
private double Break_Even;
private double Tralling_Stop;
private double Scale_Out1;
private double Scale_Out2;
private double Scale_Out3;
private double Scale_Out4;
#region Calculate Volume
private int CalculateVolume(double stopLossPips)
{
int result;
switch (volPercentBool)
{
case true:
double costPerPip = (double)((int)(Symbol.PipValue * 10000000)) / 100;
double posSizeForRisk = (Account.Balance * volPercent / 100) / (stopLossPips * costPerPip);
double posSizeToVol = (Math.Round(posSizeForRisk, 2) * 100000);
Print("Cost per Pip: $ {0}, || Position Size (Lot): {1}, || Position Size (Unit): {2}", costPerPip, Math.Round(posSizeForRisk, 2), posSizeToVol);
result = (int)Symbol.NormalizeVolumeInUnits(posSizeToVol, RoundingMode.ToNearest);
result = result > 150000 ? 150000 : result;
result = result <= 1000 ? 2000 : result;
Print("{0}% of Account Balance used for Volume! || Volume equals {1}", volPercent, result);
break;
default:
result = volQty;
Print("Volume Quantity Used! Volume equals {0}", result);
break;
}
return result;
}
#endregion
/// This is called when the robot first starts, it is only called once.
protected override void OnStart()
{
ATR = Indicators.AverageTrueRange(14, MovingAverageType.Exponential);
PAC_hi = Indicators.MovingAverage(Bars.HighPrices, FastPeriods, MAType);
PAC_low = Indicators.MovingAverage(Bars.LowPrices, FastPeriods, MAType);
slowMa = Indicators.MovingAverage(SourceSeries, SlowPeriods, MAType);
RSI = Indicators.RelativeStrengthIndex(Source, Periods);
_dms = Indicators.DirectionalMovementSystem(Period);
SPREAD = (double)((int)Math.Round(Symbol.Spread / Symbol.PipSize, 5));
if (ATR_Protection)
{
Stop_Loss = (double)((int)Math.Round((ATR.Result.Last(1)) * StopLoss_ATR / Symbol.PipSize, 5));
Take_Profit = (double)((int)Math.Round((ATR.Result.Last(1)) * TakeProfit_ATR / Symbol.PipSize, 5));
Break_Even = (double)((int)Math.Round((ATR.Result.Last(1)) * Trigger_ATR / Symbol.PipSize, 5));
Tralling_Stop = (double)((int)Math.Round((ATR.Result.Last(1)) * TrallingStop_ATR / Symbol.PipSize, 5));
Scale_Out1 = (double)((int)Math.Round((ATR.Result.Last(1)) * TakeProfit1_ATR / Symbol.PipSize, 5));
Scale_Out2 = (double)((int)Math.Round((ATR.Result.Last(1)) * TakeProfit2_ATR / Symbol.PipSize, 5));
Scale_Out3 = (double)((int)Math.Round((ATR.Result.Last(1)) * TakeProfit3_ATR / Symbol.PipSize, 5));
Scale_Out4 = (double)((int)Math.Round((ATR.Result.Last(1)) * TakeProfit4_ATR / Symbol.PipSize, 5));
}
else if (!ATR_Protection)
{
Stop_Loss = StopLoss_Pips;
Take_Profit = TakeProfit_Pips;
Break_Even = Trigger_Pips;
Tralling_Stop = TrallingStop_Pips;
Scale_Out1 = TakeProfit1_Pips;
Scale_Out2 = TakeProfit2_Pips;
Scale_Out3 = TakeProfit3_Pips;
Scale_Out4 = TakeProfit4_Pips;
}
VolumeInUnits = CalculateVolume(Stop_Loss);
// Subscribe to the Trade Closing event
Positions.Closed += OnPositionsClosed;
}
/// This event handler is called every tick or every time the price changes for the symbol.
protected override void OnTick()
{
var longPosition = Positions.Find(PositionId, SymbolName, TradeType.Buy);
var shortPosition = Positions.Find(PositionId, SymbolName, TradeType.Sell);
var Open = Bars.OpenPrices.Last(1);
var Close = Bars.ClosePrices.Last(1);
var Range = Bars.HighPrices.Last(1) - Bars.LowPrices.Last(1);
var GreenBar = Bars.ClosePrices.Last(1) - Bars.OpenPrices.Last(1);
var RedBar = Bars.OpenPrices.Last(1) - Bars.ClosePrices.Last(1);
var PAC_High = PAC_hi.Result.Last(1);
var PAC_Low = PAC_low.Result.Last(1);
var Trend = slowMa.Result.Last(1);
var Rsi = RSI.Result.Last(1);
var ADX = _dms.ADX.LastValue;
var DIPlus = _dms.DIPlus.Last(1);
var DIMinus = _dms.DIMinus.Last(1);
if ((GreenBar / Range) >= 0.65 && Close > PAC_High && Open < PAC_High && PAC_Low >= Trend && Rsi >= 50 && Rsi < OverBought && ADX >= Threshold && DIPlus > DIMinus && SPREAD <= MaxSpread && longPosition == null)
{
if (shortPosition != null)
ClosePosition(shortPosition);
ExecuteMarketRangeOrder(TradeType.Buy, this.Symbol.Name, VolumeInUnits, Slippage, Symbol.Bid, PositionId.ToString(), Stop_Loss, Take_Profit, Comment);
if (LastResult.IsSuccessful)
Print("PID: [ {0} ] Open {1} {2} || Volume: {3} || Spread: {4} || Stoploss: {5} || TakeProfit: {6} || {7} {8}:{9}:{10}", LastResult.Position.Id, "Long Position for ", SymbolName, LastResult.Position.VolumeInUnits, SPREAD, Stop_Loss, Take_Profit, Server.Time.DayOfWeek, Server.Time.Hour,
Server.Time.Minute, Server.Time.Second);
}
else if ((RedBar / Range) >= 0.65 && Close < PAC_Low && Open > PAC_Low && PAC_High <= Trend && Rsi <= 50 && Rsi > OverSold && ADX >= Threshold && DIPlus < DIMinus && SPREAD <= MaxSpread && shortPosition == null)
{
if (longPosition != null)
ClosePosition(longPosition);
ExecuteMarketRangeOrder(TradeType.Sell, this.Symbol.Name, VolumeInUnits, Slippage, Symbol.Bid, PositionId.ToString(), Stop_Loss, Take_Profit, Comment);
if (LastResult.IsSuccessful)
Print("PID: [ {0} ] Open {1} {2} || Volume: {3} || Spread: {4} || Stoploss: {5} || TakeProfit: {6} || {7} {8}:{9}:{10}", LastResult.Position.Id, "Short Position for ", SymbolName, LastResult.Position.VolumeInUnits, SPREAD, Stop_Loss, Take_Profit, Server.Time.DayOfWeek, Server.Time.Hour,
Server.Time.Minute, Server.Time.Second);
}
if (Close > PAC_High || ((GreenBar / Range) >= 0.75 && Close > PAC_Low))
{
if (ExitStrategy && shortPosition != null)
ClosePosition(shortPosition);
}
else if (Close < PAC_Low || ((RedBar / Range) >= 0.75 && Close < PAC_High))
{
if (ExitStrategy && longPosition != null)
ClosePosition(longPosition);
}
var position = Positions.Find(PositionId);
if (position != null && entrar)
{
_symbolInfo = Symbols.GetSymbolInfo(position.SymbolName);
_levels = GetTakeProfitLevels();
ValidateLevels(position);
entrar = false;
}
if (position == null)
{
entrar = true;
}
profit123();
if (TrallingStopEnabled && OnTickTrallingStopEnabled)
{
TrallingStop();
}
if (BreakEvenEnabled && OnTickBreakEvenEnabled)
{
BreakEvenIfNeeded();
}
}
/// a handler that is called on stopping the cBot.
protected override void OnStop()
{
// Put your deinitialization logic here
}
/// a special Robot class member that handles situations with errors.
protected override void OnError(Error error)
{
Print("Error Code {0}", error.Code);
}
/// a special event handler that is called each time a new bar is drawn on chart.
/// if you want your robot to act only when the previous bar is closed, this standard handler is where you put your main trading code.
protected override void OnBar()
{
if (BreakEvenEnabled && OnTickBreakEvenEnabled == false)
{
BreakEvenIfNeeded();
}
if (TrallingStopEnabled && OnTickTrallingStopEnabled == false)
{
TrallingStop();
}
}
protected void profit123()
{
var position = Positions.Find(PositionId);
if (position != null)
{
var reachedLevels = _levels.Where(level => level.IsEnabled && !level.IsTriggered && level.Pips <= position.Pips);
foreach (var reachedLevel in reachedLevels)
{
reachedLevel.MarkAsTriggered();
Print("PID: [ {0} ] Scale Out {1} || {2} is reached. || Gain/Loss {3} Pips / $ {4} || {5} {6}:{7}:{8}", LastResult.Position.Id, SymbolName, reachedLevel.Name, LastResult.Position.Pips, LastResult.Position.NetProfit, Server.Time.DayOfWeek, Server.Time.Hour, Server.Time.Minute, Server.Time.Second);
var volumeToClose = Math.Min(reachedLevel.Volume, position.VolumeInUnits);
if (position.TradeType == TradeType.Buy)
{
Chart.DrawIcon("poMarker1" + Bars.OpenTimes.Last(0).ToString() + "" + reachedLevel.Pips, ChartIconType.Square, Bars.OpenTimes.LastValue, Bars.LowPrices.Last(0) - (reachedLevel.Pips * Symbol.PipSize), reachedLevel.mColor);
}
else
{
Chart.DrawIcon("poMarker1" + Bars.OpenTimes.Last(0).ToString() + "" + reachedLevel.Pips, ChartIconType.Square, Bars.OpenTimes.LastValue, Bars.HighPrices.Last(0) + (reachedLevel.Pips * Symbol.PipSize), reachedLevel.mColor);
}
if (onlyShowEnabled == false)
{
ClosePosition(position, volumeToClose);
}
}
}
}
protected void TrallingStop()
{
var position = Positions.Find(PositionId);
if (position != null)
{
if (position.TradeType == TradeType.Sell)
{
double? stopLossPrice = Symbol.Bid + Tralling_Stop * Symbol.PipSize;
if (Tralling_Stop != 0 && stopLossPrice < position.StopLoss && stopLossPrice < position.EntryPrice)
if (stopLossPrice - Symbol.Bid > 0)
{
ModifyPosition(position, stopLossPrice, position.TakeProfit);
Print("PID: [ {0} ] Trailing {1} || New StopLoss: {2} || {3} {4}:{5}:{6}", LastResult.Position.Id, SymbolName, LastResult.Position.StopLoss, Server.Time.DayOfWeek, Server.Time.Hour, Server.Time.Minute, Server.Time.Second);
}
}
else
{
double stopLossPrice = Symbol.Ask - Tralling_Stop * Symbol.PipSize;
if (Tralling_Stop != 0 && stopLossPrice > position.StopLoss && stopLossPrice > position.EntryPrice)
if (stopLossPrice - Symbol.Ask < 0)
{
ModifyPosition(position, stopLossPrice, position.TakeProfit);
Print("PID: [ {0} ] Trailing {1} || New StopLoss: {2} || {3} {4}:{5}:{6}", LastResult.Position.Id, SymbolName, LastResult.Position.StopLoss, Server.Time.DayOfWeek, Server.Time.Hour, Server.Time.Minute, Server.Time.Second);
}
}
}
}
private void OnPositionsClosed(PositionClosedEventArgs args)
{
// check if the position has been closed due to stoploss or takeprofit or any other(stop out etc)
if (args.Reason == PositionCloseReason.StopLoss)
{
Print("PID: [ {0} ] Stoploss Hit {1} || Gain/Loss {2}Pips / $ {3} || Spread:{4} || {5} {6}:{7}:{8} ", LastResult.Position.Id, SymbolName, LastResult.Position.Pips, LastResult.Position.NetProfit, SPREAD, Server.Time.DayOfWeek, Server.Time.Hour, Server.Time.Minute, Server.Time.Second);
}
else if (args.Reason == PositionCloseReason.TakeProfit)
{
Print("PID: [ {0} ] Take Profit Hit {1} || Gain/Loss {2}Pips / $ {3} || Spread:{4} || {5} {6}:{7}:{8}", LastResult.Position.Id, SymbolName, LastResult.Position.Pips, LastResult.Position.NetProfit, SPREAD, Server.Time.DayOfWeek, Server.Time.Hour, Server.Time.Minute, Server.Time.Second);
}
else if (args.Reason == PositionCloseReason.Closed)
{
Print("PID: [ {0} ] Exit Trade {1} || Gain/Loss {2}Pips / $ {3} || Spread:{4} || {5} {6}:{7}:{8}", LastResult.Position.Id, SymbolName, LastResult.Position.Pips, LastResult.Position.NetProfit, SPREAD, Server.Time.DayOfWeek, Server.Time.Hour, Server.Time.Minute, Server.Time.Second);
}
else if (args.Reason == PositionCloseReason.StopOut)
{
Print("PID: [ {0} ] StopOut {1} || Gain/Loss {2}Pips / $ {3} || Spread:{4} || {5} {6}:{7}:{8}", LastResult.Position.Id, SymbolName, LastResult.Position.Pips, LastResult.Position.NetProfit, SPREAD, Server.Time.DayOfWeek, Server.Time.Hour, Server.Time.Minute, Server.Time.Second);
}
}
private void ValidateLevels(Position position)
{
MakeSureAnyLevelEnabled();
ValidateTotalVolume(position);
ValidateReachedLevels(position);
ValidateVolumes();
}
private void ValidateVolumes()
{
var enabledLevels = _levels.Where(level => level.IsEnabled);
foreach (var level in enabledLevels)
{
if (level.Volume < _symbolInfo.VolumeInUnitsMin)
PrintErrorAndStop("Volume for " + _symbolInfo.Name + " cannot be less than " + _symbolInfo.VolumeInUnitsMin);
if (level.Volume > _symbolInfo.VolumeInUnitsMax)
PrintErrorAndStop("Volume for " + _symbolInfo.Name + " cannot be greater than " + _symbolInfo.VolumeInUnitsMax);
if (level.Volume % _symbolInfo.VolumeInUnitsMin != 0)
PrintErrorAndStop("Volume " + level.Volume + " is invalid");
}
}
private void ValidateReachedLevels(Position position)
{
var reachedLevel = _levels.FirstOrDefault(l => l.Pips <= position.Pips);
if (reachedLevel != null)
PrintErrorAndStop("Level " + reachedLevel.Name + " is already reached. The amount of Pips must be more than the amount of Pips that the Position is already gaining");
}
private void MakeSureAnyLevelEnabled()
{
if (_levels.All(level => !level.IsEnabled))
PrintErrorAndStop("You have to enable at least one \"Take Profit\" in cBot Parameters");
}
private void ValidateTotalVolume(Position position)
{
var totalVolume = _levels.Where(level => level.IsEnabled).Sum(level => level.Volume);
if (totalVolume > position.VolumeInUnits)
PrintErrorAndStop("The sum of all Take Profit respective volumes cannot be larger than the Position's volume");
}
private TakeProfitLevel[] GetTakeProfitLevels()
{
return new[]
{
new TakeProfitLevel("Take Profit 1", TakeProfit1Enabled, Scale_Out1, TakeProfit1Volume, Color.LightBlue),
new TakeProfitLevel("Take Profit 2", TakeProfit2Enabled, Scale_Out2, TakeProfit2Volume, Color.SkyBlue),
new TakeProfitLevel("Take Profit 3", TakeProfit3Enabled, Scale_Out3, TakeProfit3Volume, Color.MidnightBlue),
new TakeProfitLevel("Take Profit 4", TakeProfit4Enabled, Scale_Out4, TakeProfit4Volume, Color.Blue)
};
}
private void PrintErrorAndStop(string errorMessage)
{
Print(errorMessage);
// Stop();
// throw new Exception(errorMessage);
}
/// Call custom class method to move StopLoss to BreakEven
private void BreakEvenIfNeeded()
{
var position = Positions.Find(PositionId);
if (position == null)
return;
if (position.Pips < Break_Even)
return;
var desiredNetProfitInDepositAsset = AddPips * _symbolInfo.PipValue * position.VolumeInUnits;
var desiredGrossProfitInDepositAsset = desiredNetProfitInDepositAsset - position.Commissions * 2 - position.Swap;
var quoteToDepositRate = _symbolInfo.PipValue / _symbolInfo.PipSize;
var priceDifference = desiredGrossProfitInDepositAsset / (position.VolumeInUnits * quoteToDepositRate);
var priceAdjustment = GetPriceAdjustmentByTradeType(position.TradeType, priceDifference);
var breakEvenLevel = position.EntryPrice + priceAdjustment;
var roundedBreakEvenLevel = RoundPrice(breakEvenLevel, position.TradeType);
if (position.TradeType == TradeType.Sell && position.StopLoss < position.EntryPrice)
return;
if (position.TradeType == TradeType.Buy && position.StopLoss > position.EntryPrice)
return;
ModifyPosition(position, roundedBreakEvenLevel, position.TakeProfit);
Print("PID: [ {0} ] Break Even {1} || ({2} - {3}) || {4} {5}:{6}:{7}", LastResult.Position.Id, SymbolName, roundedBreakEvenLevel, position.StopLoss, Server.Time.DayOfWeek, Server.Time.Hour, Server.Time.Minute, Server.Time.Second);
}
private double RoundPrice(double price, TradeType tradeType)
{
var multiplier = Math.Pow(10, _symbolInfo.Digits);
if (tradeType == TradeType.Buy)
return Math.Ceiling(price * multiplier) / multiplier;
return Math.Floor(price * multiplier) / multiplier;
}
private static double GetPriceAdjustmentByTradeType(TradeType tradeType, double priceDifference)
{
if (tradeType == TradeType.Buy)
return priceDifference;
return -priceDifference;
}
}
internal class TakeProfitLevel
{
public string Name { get; private set; }
public bool IsEnabled { get; private set; }
public double Pips { get; private set; }
public int Volume { get; private set; }
public bool IsTriggered { get; private set; }
public Color mColor;
public TakeProfitLevel(string name, bool isEnabled, double pips, int volume, Color c)
{
Name = name;
IsEnabled = isEnabled;
Pips = pips;
Volume = volume;
mColor = c;
}
public void MarkAsTriggered()
{
IsTriggered = true;
}
}
}
TR
traderfxmaster007
Joined on 09.07.2019
- Distribution: Free
- Language: C#
- Trading platform: cTrader Automate
- File name: C-3PO (Unimate).algo
- Rating: 5
- Installs: 2149
- Modified: 13/10/2021 09:54
Warning! Running cBots downloaded from this section may lead to financial losses. Use them at your own risk.
Note that publishing copyrighted material is strictly prohibited. If you believe there is copyrighted material in this section, please use the Copyright Infringement Notification form to submit a claim.
Comments
Log in to add a comment.
RI
Thanks for the bot, really nice.
非常好,感谢你