Description
Hi, guys!
We have just released an innovative Expert Advisor exclusively designed for the cTrader platform. It is a fully automated Forex trading robot with a built-in Ichimoku Kinko Hyo indicator.
This strategy is:
✅ User-friendly.
✅ Configurable.
✅ Equipped with customizable SL, TP, Break-Even, Trailing Stop, and money management features.
✅ Designed with all required functions to manage positions.
Features
The Ichimoku Cloud system can:
- Monitor the crossing of two indicator lines (the first mode). All you need to do is to select the necessary lines and a bar.
- Track down if the price crosses one of the lines (the second mode). You can choose the line, current market price, or bar closing price.
- Show when it is safe to buy, safe to sell or stay out of the market.
- Identify whether you should close a position by momentum or have several positions of the same type.
Parameters
We have equipped our EA with more than 14 additional parameters. So, you can change them at your will.
Note! Try this EA on your demo account first before going live.
Other Products
PSAR Strategy:
ADR Custom Indicator:
Daily H/L Custom Indicator:
Contact Info
Contact us via support@4xdev.com
Check out our cozy Telegram blog for traders: https://t.me/Forexdev
Visit our website to find more tools and programming services: https://bit.ly/44BFRG3
Take a look at our YouTube channel: https://www.youtube.com/channel/UChsDb4Q8X2Vl5DJ7H8PzlHQ
Trade different — with 4xDev.
using cAlgo.API;
using cAlgo.API.Indicators;
using System;
namespace cAlgo.Robots
{
[Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class IchimokuCloudSystem : Robot
{
public enum ENUM_TP_TYPE
{
Fixed_TP = 0,
// Fixed TP
Risk_Ratio = 1
// Risk Ratio
}
public enum ENUM_RISK_SOURCE
{
Equity,
/*Equity*/ Balance
}
/*Balance*/ public enum ENUM_LOT_TYPE
{
Fixed_Lot = 0,
// Fixed Lot
Percent_Lot = 1
//Percent Lot
//Fixed_Amount = 2
//Fixed amount
}
public enum ENUM_CROSS_TYPE
{
Ask_Bid = 1,
// Ask/Bid
Close_Price = 0
// Close Price
}
public enum ENUM_ICHIMOKY_LINES
{
TENKANSEN = 1,
//Tenkan-sen
KIJUNSEN = 2,
//Kijun-sen
SENKOUSPANA = 3,
//Senkou Span A
SENKOUSPANB = 4,
//Senkou Span B
CHIKOUSPAN = 5
//Chikou Span
}
public enum ENUM_ICHIMOKY_LINES_PRICE
{
TENKANSEN_ = 1,
//Tenkan-sen
KIJUNSEN_ = 2,
//Kijun-sen
SENKOUSPANA_ = 3,
//Senkou Span A
SENKOUSPANB_ = 4
//Senkou Span B
}
public enum ENUM_BAR_CHECK
{
Current_Bar = 0,
//Current Bar
Formed_Bar = 1
//Formed Bar
}
#region Input Signal Parameters
[Parameter("Open on Price and Line Crossing", Group = "Signal Parameters", DefaultValue = false)]
public bool usePriceCross { get; set; }
[Parameter("Open on current bar", Group = "Signal Parameters", DefaultValue = false)]
public bool openOnCurrentBar { get; set; }
[Parameter("Applied price", Group = "Signal Parameters", DefaultValue = ENUM_CROSS_TYPE.Close_Price)]
public ENUM_CROSS_TYPE priceType { get; set; }
[Parameter("Ichimoky Line", Group = "Signal Parameters", DefaultValue = ENUM_ICHIMOKY_LINES_PRICE.KIJUNSEN_)]
public ENUM_ICHIMOKY_LINES_PRICE priceLine { get; set; }
[Parameter("Open on Lines Crossing", Group = "Signal Parameters", DefaultValue = false)]
public bool useLineCross { get; set; }
[Parameter("Bar to Check", Group = "Signal Parameters", DefaultValue = ENUM_BAR_CHECK.Formed_Bar)]
public ENUM_BAR_CHECK barCheck { get; set; }
[Parameter("Ichimoky Line #1", Group = "Signal Parameters", DefaultValue = ENUM_ICHIMOKY_LINES.TENKANSEN)]
public ENUM_ICHIMOKY_LINES lineCross1 { get; set; }
[Parameter("Ichimoky Line #2", Group = "Signal Parameters", DefaultValue = ENUM_ICHIMOKY_LINES.KIJUNSEN)]
public ENUM_ICHIMOKY_LINES lineCross2 { get; set; }
#endregion
#region Input Trade Parameters
[Parameter("Label", Group = "Trade Parameters", DefaultValue = "Ichimoku Strategy")]
public string Label { get; set; }
[Parameter("Stop Loss in pips", Group = "Trade Parameters", DefaultValue = 0)]
public double SL { get; set; }
[Parameter("Take Profit type", Group = "Trade Parameters", DefaultValue = ENUM_TP_TYPE.Fixed_TP)]
public ENUM_TP_TYPE tpType { get; set; }
[Parameter("Take Profit value", Group = "Trade Parameters", DefaultValue = 0)]
public double TP { get; set; }
[Parameter("Close on the opposite signal", Group = "Trade Parameters", DefaultValue = true)]
public bool oppositeClose { get; set; }
[Parameter("Max Orders", Group = "Trade Parameters", DefaultValue = 1)]
public int maxOrders { get; set; }
[Parameter("Use Reverse Trade", Group = "Trade Parameters", DefaultValue = true)]
public bool reverseTrade { get; set; }
#endregion
#region Input Ichimoku Parameters
[Parameter("Tenkan-sen", Group = "Ichimoku Parameters", DefaultValue = 9)]
public int tenkanSen { get; set; }
[Parameter("Kijun-sen", Group = "Ichimoku Parameters", DefaultValue = 26)]
public int kijunSen { get; set; }
[Parameter("Senkou Span B", Group = "Ichimoku Parameters", DefaultValue = 52)]
public int senkou { get; set; }
#endregion
#region Input Lot Size Parameters
[Parameter("Lot Type", Group = "Lot Size", DefaultValue = ENUM_LOT_TYPE.Fixed_Lot)]
public ENUM_LOT_TYPE lotType { get; set; }
[Parameter("Risk Source", Group = "Lot Size", DefaultValue = ENUM_RISK_SOURCE.Balance)]
public ENUM_RISK_SOURCE riskSource { get; set; }
[Parameter("Risk/Lot Value", Group = "Lot Size", DefaultValue = 0.1)]
public double risk { get; set; }
#endregion
#region Input Break Even Parameters
[Parameter("Use BreakEven", Group = "BreakEven", DefaultValue = false)]
public bool UseBE { get; set; }
[Parameter("BreakEven Start(pips)", Group = "BreakEven", DefaultValue = 10)]
public double BEStart { get; set; }
[Parameter("BreakEven Profit(pips)", Group = "BreakEven", DefaultValue = 0)]
public double BEProfit { get; set; }
#endregion
private IchimokuKinkoHyo ichimokuKinkoHyo;
protected override void OnStart()
{
ichimokuKinkoHyo = Indicators.IchimokuKinkoHyo(tenkanSen, kijunSen, senkou);
if (priceType == ENUM_CROSS_TYPE.Ask_Bid)
{
lastAsk = Ask;
lastBid = Bid;
}
else
{
lastClose = Bars.ClosePrices.Last(0);
}
linePricePrev = GetIchiPrice(priceLine, 0);
// Put your initialization logic here
}
double lastAsk;
double lastBid;
double lastClose;
double linePricePrev;
double lastCrossLine1;
double lastCrossLine2;
double line1;
double line2;
double line1Prev;
double line2Prev;
double pricePrev;
double linePrice;
DateTime lastBar;
bool waitOpen;
TradeType currentType;
protected override void OnTick()
{
if (UseBE)
BreakEven();
// Put your core logic here
if (lastBar != Bars.OpenTimes.Last(0))
{
GetPrices();
if (waitOpen)
{
waitOpen = false;
if (CalculateOrders() < maxOrders)
{
OpenOrder(currentType);
}
}
if (barCheck == ENUM_BAR_CHECK.Formed_Bar)
{
lastBar = Bars.OpenTimes.Last(0);
}
if (useLineCross)
{
if (CheckCross(TradeType.Buy, line1, line1Prev, line2, line2Prev))
{
if (oppositeClose)
{
CloseOrders(TradeType.Sell);
}
if (CalculateOrders() < maxOrders)
{
OpenOrder(TradeType.Buy);
if (barCheck == 0)
{
lastBar = Bars.OpenTimes.Last(0);
}
}
}
if (CheckCross(TradeType.Sell, line1, line1Prev, line2, line2Prev))
{
if (oppositeClose)
{
CloseOrders(TradeType.Buy);
}
if (CalculateOrders() < maxOrders)
{
OpenOrder(TradeType.Sell);
if (barCheck == 0)
{
lastBar = Bars.OpenTimes.Last(0);
}
}
}
}
if (usePriceCross)
{
if ((priceType == ENUM_CROSS_TYPE.Ask_Bid && CheckCross(TradeType.Buy, linePrice, linePricePrev, Ask, lastAsk)) || (priceType == ENUM_CROSS_TYPE.Close_Price && CheckCross(TradeType.Buy, linePrice, linePricePrev, Bars.ClosePrices.Last(0), lastClose)))
{
if (oppositeClose)
{
CloseOrders(TradeType.Sell);
}
if (!openOnCurrentBar)
{
waitOpen = true;
currentType = TradeType.Buy;
if (barCheck == 0)
{
lastBar = Bars.OpenTimes.Last(0);
}
}
else
{
if (CalculateOrders() < maxOrders)
{
OpenOrder(TradeType.Buy);
if (barCheck == 0)
{
lastBar = Bars.OpenTimes.Last(0);
}
}
}
}
if ((priceType == ENUM_CROSS_TYPE.Ask_Bid && CheckCross(TradeType.Sell, linePrice, linePricePrev, Bid, lastBid)) || (priceType == ENUM_CROSS_TYPE.Close_Price && CheckCross(TradeType.Sell, linePrice, linePricePrev, Bars.ClosePrices.Last(0), lastClose)))
{
if (oppositeClose)
{
CloseOrders(TradeType.Buy);
}
if (!openOnCurrentBar)
{
waitOpen = true;
currentType = TradeType.Sell;
if (barCheck == 0)
{
lastBar = Bars.OpenTimes.Last(0);
}
}
else
{
if (CalculateOrders() < maxOrders)
{
OpenOrder(TradeType.Sell);
if (barCheck == 0)
{
lastBar = Bars.OpenTimes.Last(0);
}
}
}
}
}
}
if (priceType == ENUM_CROSS_TYPE.Ask_Bid)
{
lastAsk = Ask;
lastBid = Bid;
}
else
{
lastClose = Bars.ClosePrices.Last(0);
}
linePricePrev = GetIchiPrice(priceLine, 0);
}
bool CheckOrders()
{
if (Positions.Find(Label, Symbol) != null)
return false;
return true;
}
int CalculateOrders()
{
return Positions.FindAll(Label, Symbol).Length;
}
bool CheckCross(TradeType direct, double v1, double v1prev, double v2, double v2prev)
{
if (direct == TradeType.Buy && v1prev < v2prev && v1 > v2)
return true;
if (direct == TradeType.Sell && v1prev > v2prev && v1 < v2)
return true;
return false;
}
void CloseOrders(TradeType type)
{
if (reverseTrade)
type = type == TradeType.Buy ? TradeType.Sell : TradeType.Buy;
foreach (var pos in Positions.FindAll(Label, Symbol, type))
{
ClosePosition(pos);
}
}
void OpenOrder(TradeType type)
{
if (reverseTrade)
type = type == TradeType.Buy ? TradeType.Sell : TradeType.Buy;
double op;
double tp = tpType == ENUM_TP_TYPE.Fixed_TP ? TP : SL * TP;
double sl;
double source = riskSource == ENUM_RISK_SOURCE.Balance ? Account.Balance : Account.Equity;
double volumeInUnits = 0;
if (lotType == ENUM_LOT_TYPE.Fixed_Lot)
volumeInUnits = Symbol.QuantityToVolumeInUnits(risk);
else
volumeInUnits = CalculateVolume(SL, risk, source);
if (volumeInUnits == -1)
return;
ExecuteMarketOrder(type, SymbolName, volumeInUnits, Label, SL, TP);
}
private double CalculateVolume(double stopLossPips, double riskSize, double source)
{
// source = Account.Balance or Account.Equity
double riskPerTrade = source * riskSize / 100;
double totalPips = stopLossPips;
double _volume;
double exactVolume = riskPerTrade / (Symbol.PipValue * totalPips);
if (exactVolume >= Symbol.VolumeInUnitsMin)
{
_volume = Symbol.NormalizeVolumeInUnits(exactVolume);
}
else
{
_volume = -1;
Print("Not enough Equity to place minimum trade, exactVolume " + exactVolume + " is not >= Symbol.VolumeInUnitsMin " + Symbol.VolumeInUnitsMin);
}
return _volume;
}
void GetPrices()
{
if (useLineCross)
{
int index = (int)barCheck;
int index2 = (int)barCheck;
if (lineCross1 == ENUM_ICHIMOKY_LINES.CHIKOUSPAN)
{
index = (int)barCheck;
index2 = (int)barCheck + kijunSen;
}
if (lineCross2 == ENUM_ICHIMOKY_LINES.CHIKOUSPAN)
{
index2 = (int)barCheck;
index = (int)barCheck + kijunSen;
}
if (lineCross1 == ENUM_ICHIMOKY_LINES.SENKOUSPANA || lineCross1 == ENUM_ICHIMOKY_LINES.SENKOUSPANB)
{
index += kijunSen;
}
if (lineCross2 == ENUM_ICHIMOKY_LINES.SENKOUSPANA || lineCross2 == ENUM_ICHIMOKY_LINES.SENKOUSPANB)
{
index2 += kijunSen;
}
line1 = GetIchi(lineCross1, index);
line1Prev = GetIchi(lineCross1, index + 1);
line2 = GetIchi(lineCross2, index2);
line2Prev = GetIchi(lineCross2, index2 + 1);
}
if (usePriceCross)
{
linePrice = GetIchiPrice(priceLine, 0);
}
}
double GetIchi(ENUM_ICHIMOKY_LINES line, int index)
{
switch (line)
{
case ENUM_ICHIMOKY_LINES.CHIKOUSPAN:
return ichimokuKinkoHyo.ChikouSpan.Last(index);
case ENUM_ICHIMOKY_LINES.KIJUNSEN:
return ichimokuKinkoHyo.KijunSen.Last(index);
case ENUM_ICHIMOKY_LINES.SENKOUSPANA:
return ichimokuKinkoHyo.SenkouSpanA.Last(index);
case ENUM_ICHIMOKY_LINES.SENKOUSPANB:
return ichimokuKinkoHyo.SenkouSpanB.Last(index);
case ENUM_ICHIMOKY_LINES.TENKANSEN:
return ichimokuKinkoHyo.TenkanSen.Last(index);
}
return 0;
}
double GetIchiPrice(ENUM_ICHIMOKY_LINES_PRICE line, int index)
{
switch (line)
{
case ENUM_ICHIMOKY_LINES_PRICE.KIJUNSEN_:
return ichimokuKinkoHyo.KijunSen.Last(index);
case ENUM_ICHIMOKY_LINES_PRICE.SENKOUSPANA_:
return ichimokuKinkoHyo.SenkouSpanA.Last(index);
case ENUM_ICHIMOKY_LINES_PRICE.SENKOUSPANB_:
return ichimokuKinkoHyo.SenkouSpanB.Last(index);
case ENUM_ICHIMOKY_LINES_PRICE.TENKANSEN_:
return ichimokuKinkoHyo.TenkanSen.Last(index);
}
return 0;
}
private void BreakEven()
{
if (!UseBE)
return;
foreach (var pos in Positions.FindAll(Label, SymbolName))
{
if (pos.TradeType == TradeType.Buy)
{
if (Symbol.Ask >= pos.EntryPrice + BEStart * Symbol.PipSize && (pos.StopLoss < pos.EntryPrice + BEProfit * Symbol.PipSize || pos.StopLoss == null))
{
ModifyPosition(pos, pos.EntryPrice + BEProfit * Symbol.PipSize, pos.TakeProfit);
}
}
if (pos.TradeType == TradeType.Sell)
{
if (Symbol.Bid <= pos.EntryPrice - BEStart * Symbol.PipSize && (pos.StopLoss > pos.EntryPrice - BEProfit * Symbol.PipSize || pos.StopLoss == null))
{
ModifyPosition(pos, pos.EntryPrice + BEProfit * Symbol.PipSize, pos.TakeProfit);
}
}
}
}
protected override void OnStop()
{
// Put your deinitialization logic here
}
}
}
4xDev
Joined on 11.12.2019
- Distribution: Free
- Language: C#
- Trading platform: cTrader Automate
- File name: Ichimoku_Cloud_System.algo
- Rating: 3.57
- Installs: 3043
- Modified: 21/06/2023 10:12
Comments
@Sado.Methodist. The risk / lot is a feature that enables you to choose wehther to trade by using lot size. or by using a certain percentage of your capital, this is good because you are not suppose to risk more than 2 percent of you capital. its a good risk management practice.
Can you do some changes in this Cbot?
Can someone explain please what exactly is risk/lot size?
This is a robust cbot. Thanks for sharing.