How to reference custom indicator in cBot?
How to reference custom indicator in cBot?
15 Feb 2023, 14:53
Mr PanagiotisCharalampous sends everybody with similar question to https://help.ctrader.com/ctrader-automate/guides/indicators/ , but I don's see there correct response.
I know Indicators.GetIndicator<>() function, but it doesn't work. I always get "15/02/2023 13:49:37.095 | Crashed in Initialize with NullReferenceException: Object reference not set to an instance of an object." error. I give correct type of indicator and all parameters.
Could anybody please write working simplest possible example in documentation?
Or place there useful link?
Replies
ctid5292619
17 Feb 2023, 10:17
RE:
Thank your for your response.
Could you PLEASE give me a link to working demo of custom indicator and cBot?
I'm learning to code in cTrader and I prefer to have generic simple example then something complicated (and my indicator is a little complicated), I may have trouble to use later in different circumstances.
Thank you!
@ctid5292619
ctid5292619
18 Feb 2023, 13:52
( Updated at: 18 Feb 2023, 13:56 )
RE:
I have found working example of custom indicator in cBot ( https://ctrader.com/algos/indicators/show/1086 ).
Indicator name: Renko.
I didn't test if everything is working fine, but code compiles (with many warnings as indicator is quite old).
Indicator:
using
cAlgo.API;
using
cAlgo.API.Indicators;
using
cAlgo.API.Internals;
using
cAlgo.Indicators;
using
System;
using
System.Collections.Generic;
using
System.Linq;
namespace
cAlgo
{
[Indicator(
"Renko"
, IsOverlay =
true
, AutoRescale =
true
, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public
class
Renko : Indicator
{
[Parameter(
"Renko (Pips)"
, DefaultValue = 10, MinValue = 0.1, Step = 1)]
public
double
RenkoPips {
get
;
set
; }
[Parameter(
"Bricks To Show"
, DefaultValue = 100, MinValue = 1)]
public
int
BricksToShow {
get
;
set
; }
[Parameter(
"Zoom Level"
, DefaultValue = 3, MinValue = 0, MaxValue = 5, Step = 1)]
public
double
ZoomLevel {
get
;
set
; }
[Parameter(
"Bullish Color"
, DefaultValue =
"SeaGreen"
)]
public
string
ColorBull {
get
;
set
; }
[Parameter(
"Bearish Color"
, DefaultValue =
"Tomato"
)]
public
string
ColorBear {
get
;
set
; }
[Output(
"Open"
, Color = Colors.DimGray, Thickness = 1, PlotType = PlotType.Points)]
public
IndicatorDataSeries Open {
get
;
set
; }
[Output(
"High"
, Color = Colors.DimGray, Thickness = 1, PlotType = PlotType.Points)]
public
IndicatorDataSeries High {
get
;
set
; }
[Output(
"Low"
, Color = Colors.DimGray, Thickness = 1, PlotType = PlotType.Points)]
public
IndicatorDataSeries Low {
get
;
set
; }
[Output(
"Close"
, Color = Colors.DimGray, Thickness = 1, PlotType = PlotType.Points)]
public
IndicatorDataSeries Close {
get
;
set
; }
public
class
Brick
{
public
double
Open {
get
;
set
; }
public
double
Close {
get
;
set
; }
}
public
List<Brick> Bricks =
new
List<Brick>();
private
double
closeLastValue, thickness, renkoPips, renkoLastValue;
private
Colors colorBull, colorBear;
private
bool
colorError;
private
int
lastCount;
protected
override
void
Initialize()
{
if
(!Enum.TryParse<Colors>(ColorBull,
out
colorBull) || !Enum.TryParse<Colors>(ColorBear,
out
colorBear))
colorError =
true
;
renkoPips = RenkoPips * Symbol.PipSize;
thickness = Math.Pow(2, ZoomLevel) - (ZoomLevel > 0 ? 1 : 0);
renkoLastValue = 0;
}
public
override
void
Calculate(
int
index)
{
if
(colorError)
{
ChartObjects.DrawText(
"Error0"
,
"{o,o}\n/)_)\n \" \"\nOops! Incorrect colors."
, StaticPosition.TopCenter, Colors.Gray);
return
;
}
if
(renkoLastValue == 0)
{
var open = MarketSeries.Open.LastValue;
renkoLastValue = open - (open % renkoPips) + renkoPips / 2;
}
closeLastValue = MarketSeries.Close.LastValue;
while
(closeLastValue >= renkoLastValue + renkoPips * 1.5)
{
renkoLastValue += renkoPips;
Bricks.Insert(0,
new
Brick
{
Open = renkoLastValue - renkoPips / 2,
Close = renkoLastValue + renkoPips / 2
});
if
(Bricks.Count() > BricksToShow)
Bricks.RemoveRange(BricksToShow, Bricks.Count() - BricksToShow);
if
(IsLastBar)
UpdateHistory(index);
}
while
(closeLastValue <= renkoLastValue - renkoPips * 1.5)
{
renkoLastValue -= renkoPips;
Bricks.Insert(0,
new
Brick
{
Open = renkoLastValue + renkoPips / 2,
Close = renkoLastValue - renkoPips / 2
});
if
(Bricks.Count() > BricksToShow)
Bricks.RemoveRange(BricksToShow, Bricks.Count() - BricksToShow);
if
(IsLastBar)
UpdateHistory(index);
}
bool
isNewBar = MarketSeries.Close.Count > lastCount;
if
(IsLastBar && isNewBar)
{
UpdateHistory(index);
Open[index - BricksToShow] =
double
.NaN;
High[index - BricksToShow] =
double
.NaN;
Low[index - BricksToShow] =
double
.NaN;
Close[index - BricksToShow] =
double
.NaN;
lastCount = MarketSeries.Close.Count;
}
if
(IsRealTime)
UpdateLive(index);
}
private
void
UpdateHistory(
int
index)
{
for
(
int
i = 0; i < BricksToShow - 1 && i < Bricks.Count() - 1; i++)
{
var color = Bricks[i].Open < Bricks[i].Close ? colorBull : colorBear;
ChartObjects.DrawLine(
string
.Format(
"renko.Last({0})"
, i + 1), index - i - 1, Bricks[i].Open, index - i - 1, Bricks[i].Close, color, thickness, LineStyle.Solid);
Open[index - i - 1] = Bricks[i].Open;
High[index - i - 1] = Math.Max(Bricks[i].Open, Bricks[i].Close);
Low[index - i - 1] = Math.Min(Bricks[i].Open, Bricks[i].Close);
Close[index - i - 1] = Bricks[i].Close;
}
}
private
void
UpdateLive(
int
index)
{
double
y1, y2;
var top = Math.Max(Bricks[0].Open, Bricks[0].Close);
var bottom = Math.Min(Bricks[0].Open, Bricks[0].Close);
if
(closeLastValue > top)
y1 = top;
else
if
(closeLastValue < bottom)
y1 = bottom;
else
y1 = closeLastValue;
y2 = closeLastValue;
var colorLive = y1 < y2 ? colorBull : colorBear;
ChartObjects.DrawLine(
"renko.Live"
, index, y1, index, y2, colorLive, thickness, LineStyle.Solid);
Open[index] = y1;
High[index] = y1 > y2 ? y1 : y2;
Low[index] = y1 < y2 ? y1 : y2;
Close[index] = y2;
}
}
}
and cBot:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using cAlgo.API;
using cAlgo.API.Collections;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;namespace cAlgo.Robots
{
[Robot(AccessRights = AccessRights.None)]
public class ReferencecustomindicatordemocBot : Robot
{
public double RenkoPips = 10;
public int BricksToShow = 10;
private Renko renko;
protected override void OnStart()
{
renko = Indicators.GetIndicator<Renko>(RenkoPips, BricksToShow, 3, "SeaGreen", "Tomato");
}
protected override void OnTick()
{
bool isLastBrickBullish = renko.Open.Last(1) < renko.Close.Last(1);
if (isLastBrickBullish)
{
ExecuteMarketOrder(TradeType.Buy, Symbol, 1000);
}
}
}
}
@ctid5292619
ctid5292619
18 Feb 2023, 14:10
RE:
I have found example of custom indicator in cBot, but I need also more complicated demo, when cBot is using outputs of custom indicator.
Could you please Mr PanagiotisChar place a link to such example?
Thank you!
@ctid5292619
PanagiotisChar
16 Feb 2023, 15:57
Hi there,
The exception indicates that you are doing something wrong in your indicator code. Share your cBot and indicator code so that we can advise further.
Aieden Technologies
Need help? Join us on Telegram
Need premium support? Trade with us
@PanagiotisChar