Topics
Forum Topics not found
Replies
amusleh
06 Apr 2021, 10:47
Hi,
This sample cBot might help you:
using cAlgo.API;
using System;
using System.Globalization;
namespace cAlgo.Robots
{
[Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.FullAccess)]
public class TradeTime : Robot
{
private TimeSpan _startTime, _endTime;
[Parameter("Start Time", DefaultValue = "07:00:00", Group = "Time Filter")]
public string StartTime { get; set; }
[Parameter("End Time", DefaultValue = "16:00:00", Group = "Time Filter")]
public string EndTime { get; set; }
private DateTime CurrentTime
{
get { return Server.TimeInUtc.Add(-Application.UserTimeOffset); }
}
private bool IsTimeCorrect
{
get { return (_startTime > _endTime && (CurrentTime.TimeOfDay >= _startTime || CurrentTime.TimeOfDay <= _endTime)) || (_startTime < _endTime && (CurrentTime.TimeOfDay >= _startTime && CurrentTime.TimeOfDay <= _endTime)); }
}
protected override void OnStart()
{
if (!TimeSpan.TryParse(StartTime, CultureInfo.InvariantCulture, out _startTime))
{
Print("Invalid start time input");
Stop();
}
if (!TimeSpan.TryParse(EndTime, CultureInfo.InvariantCulture, out _endTime))
{
Print("Invalid end time input");
Stop();
}
}
protected override void OnBar()
{
// Return if current time is not in start/end time range
if (!IsTimeCorrect) return;
}
}
}
Please take a look on Server.Time, Server.TimeInUtc, Application.UserTimeOffset, .NET TimeSpan, and DateTime.
If you know the C# basics and cTrader automate API references then you can easily do it.
@amusleh
amusleh
05 Apr 2021, 19:01
Hi,
Try this: https://www.algodeveloper.com/product/volume-profile/
@amusleh
amusleh
04 Apr 2021, 13:27
Hi,
Try this:
using cAlgo.API;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
namespace cAlgo
{
[Indicator(IsOverlay = false, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class MTFMACD : Indicator
{
private MacdCrossOver _macd;
private Bars _baseTimeFrameBars;
[Output("MACD Histogram,", LineColor = "#FF40E0D0", PlotType = PlotType.Histogram, LineStyle = LineStyle.Solid, Thickness = 5)]
public IndicatorDataSeries MACD_Histogram { get; set; }
[Output("MACD Line,", LineColor = "Blue", PlotType = PlotType.Line, LineStyle = LineStyle.Solid, Thickness = 1)]
public IndicatorDataSeries MACD_Line { get; set; }
[Output("Signal Line,", LineColor = "Red", PlotType = PlotType.Line, LineStyle = LineStyle.Lines, Thickness = 1)]
public IndicatorDataSeries Signal_Line { get; set; }
[Parameter("Base Timeframe", DefaultValue = "Hour")]
public TimeFrame BaseTimeFrame { get; set; }
[Parameter("Applied price", DefaultValue = Price.Close)]
public Price Source { get; set; }
[Parameter("Long Period", DefaultValue = 26)]
public int LongPeriod { get; set; }
[Parameter("Short Period", DefaultValue = 12)]
public int ShortPeriod { get; set; }
[Parameter("Signal Period", DefaultValue = 9)]
public int SignalPeriod { get; set; }
protected override void Initialize()
{
_baseTimeFrameBars = MarketData.GetBars(BaseTimeFrame);
var baseSeries = GetBaseSeries();
_macd = Indicators.MacdCrossOver(baseSeries, LongPeriod, ShortPeriod, SignalPeriod);
}
public override void Calculate(int index)
{
var baseSeriesIndex = _baseTimeFrameBars.OpenTimes.GetIndexByTime(Bars.OpenTimes[index]);
MACD_Histogram[index] = _macd.Histogram[baseSeriesIndex];
MACD_Line[index] = _macd.MACD[baseSeriesIndex];
Signal_Line[index] = _macd.Signal[baseSeriesIndex];
}
private DataSeries GetBaseSeries()
{
switch (Source)
{
case Price.Open:
return _baseTimeFrameBars.OpenPrices;
case Price.Close:
return _baseTimeFrameBars.ClosePrices;
case Price.High:
return _baseTimeFrameBars.HighPrices;
case Price.Low:
return _baseTimeFrameBars.LowPrices;
case Price.Median:
return _baseTimeFrameBars.MedianPrices;
case Price.Typical:
return _baseTimeFrameBars.TypicalPrices;
case Price.Weighted:
return _baseTimeFrameBars.WeightedPrices;
default:
return _baseTimeFrameBars.ClosePrices;
}
}
}
public enum Price
{
Open,
Close,
High,
Low,
Median,
Typical,
Weighted
}
}
Please read the API references and take a look to sample indicators/cBots code before building an indicator or cBot.
@amusleh
amusleh
04 Apr 2021, 13:17
Hi,
Try this:
using cAlgo.API;
using cAlgo.API.Indicators;
namespace cAlgo
{
[Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class EmaBiasWithCross : Robot
{
[Parameter("Source")]
public DataSeries SourceSeries { get; set; }
[Parameter("Label", DefaultValue = "EMA")]
public string Label { get; set; }
[Parameter("Slow Periods", DefaultValue = 233)]
public int SlowPeriods { get; set; }
[Parameter("Medium Periods", DefaultValue = 55)]
public int MediumPeriods { get; set; }
[Parameter("Fast Periods", DefaultValue = 21)]
public int FastPeriods { get; set; }
[Parameter("Stop Loss", DefaultValue = 10)]
public int SL { get; set; }
[Parameter("Take Profit", DefaultValue = 10)]
public double TP { get; set; }
[Parameter("Quantity (Lots)", DefaultValue = 1, MinValue = 0.01, Step = 0.01)]
public double Quantity { get; set; }
private ExponentialMovingAverage slowMa;
private double _volumeInUnits;
private ExponentialMovingAverage mediumMa;
private ExponentialMovingAverage fastMa;
protected override void OnStart()
{
fastMa = Indicators.ExponentialMovingAverage(SourceSeries, FastPeriods);
mediumMa = Indicators.ExponentialMovingAverage(SourceSeries, MediumPeriods);
slowMa = Indicators.ExponentialMovingAverage(SourceSeries, SlowPeriods);
_volumeInUnits = Symbol.QuantityToVolumeInUnits(Quantity);
}
protected override void OnBar()
{
int index = Bars.Count - 2;
Entry(index);
Exit(index);
}
private void Exit(int index)
{
var positions = Positions.FindAll(Label);
foreach (var position in positions)
{
if ((position.TradeType == TradeType.Buy && Bars.ClosePrices[index] < mediumMa.Result[index])
|| (position.TradeType == TradeType.Sell && Bars.ClosePrices[index] > mediumMa.Result[index]))
{
ClosePosition(position);
}
}
}
private void Entry(int index)
{
// Buy Only
if (Bars.ClosePrices[index] > slowMa.Result[index])
{
// if fast crosses medium upward
if (fastMa.Result[index] > mediumMa.Result[index] && fastMa.Result[index - 1] < mediumMa.Result[index - 1])
{
ExecuteMarketOrder(TradeType.Buy, SymbolName, _volumeInUnits, Label, SL, TP);
}
}
// Sell only
else if (Bars.ClosePrices[index] < slowMa.Result[index])
{
// if fast crosses medium downward
if (fastMa.Result[index] < mediumMa.Result[index] && fastMa.Result[index - 1] > mediumMa.Result[index - 1])
{
ExecuteMarketOrder(TradeType.Sell, SymbolName, _volumeInUnits, Label, SL, TP);
}
}
}
}
}
It might have some bugs, for more info please read the API references and check the sample cBots/indicators code.
@amusleh
amusleh
02 Apr 2021, 22:09
RE: RE:
PUdPUd said:
Thanks for your thoughts Afhacker. Your suggested amendment gives the following error: Error CS0136: A local variable named 'TargetLongMath' cannot be declared in this scope because it would give a different meaning to 'TargetLongMath', which is already used in a 'parent or current' scope to denote something else
We provide help here for cTrader and cTrader automate, not for C#, as I said in my previous posts please start learning C# basics:
@amusleh
amusleh
02 Apr 2021, 11:26
Hi,
You code is full of errors, please learn the basic of C# before trying to create an indicator or cBot.
You can't start your variable names in C# with a number, this is not allowed, and when you post code please use the code snippet option of editor.
We can't develop your cBot for you, we only can answer questions here.
I made some changes on your cBot code but it still has some errors as I don't had access to some of your variables and I don't know what are those variables.
using cAlgo.API;
using cAlgo.API.Internals;
using System;
namespace cAlgo.Robots
{
[Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class MyRobot : Robot
{
[Parameter(DefaultValue = 0.0)]
public double Parameter { get; set; }
//The source of the MarketSeries is obsolete: 'Use Bars Instead' Warning message
private Bars series2, series3;
private Symbol symbol2, symbol3;
[Parameter(DefaultValue = "EURUSD")]
public string Symbol2 { get; set; }
[Parameter(DefaultValue = "GBPUSD")]
public string Symbol3 { get; set; }
protected override void OnStart()
{
var dailyBars = MarketData.GetBars(TimeFrame.Daily);
dailyBars.BarOpened += OnDailyBarsBarOpened;
}
protected override void OnTick()
{
// Put your core logic here
}
protected override void OnStop()
{
// Put your deinitialization logic here
}
private void OnDailyBarsBarOpened(BarOpenedEventArgs obj)
{
//Get some data
var Lag1USDCADHigh = obj.Bars.HighPrices.Last(1);
symbol2 = Symbols.GetSymbol(Symbol2);
series2 = MarketData.GetBars(TimeFrame.Daily, Symbol2);
//Source of second warning message to use Bars.ClosePrices Instead but how to apply to external data?? var EURUSDYDaysClose = series2.Close.Last(0);
var symbol3 = Symbols.GetSymbol(Symbol3);
series3 = MarketData.GetBars(TimeFrame.Daily, Symbol3);
var Lag1GBPUSDHigh = series3.HighPrices.Last(0);
//Predifined TP and SL for Long and Short positions
var longMath = -1 + (2 * Lag1GBPUSDHigh);
var shortMath = -3 + (4 * EURUSDYDaysClose) + (5 * Lag1USDCADHigh);
var longSL = -0.6;
var shortSL = 7.0;
var longMath = -2 + (3 * Lag1GBPUSDHigh);
var shortMath = -4 + (5 * EURUSDYDaysClose) + (6 * Lag1USDCADHigh);
var longSL = -0.7;
var shortSL = 8;
var longMath = -3 + (4 * Lag1GBPUSDHigh);
var shortMath = -5 + (6 * EURUSDYDaysClose) + (7 * Lag1USDCADHigh);
var longSL = -0.8;
var shortSL = 9;
//Choose which TP and SL to use based on the value of another instrument
double TargetLongMath = 0;
if (EURUSDYDaysClose < 0.5)
{
TargetLongMath = longMath;
var LongSL = longSL;
var TargetShortMath = shortMath;
var ShortSL = shortSL;
}
else
{
if ((EURUSDYDaysClose > 0.5) && (EURUSDYDaysClose < 0.7)
{
TargetLongMath = longMath;
var LongSL = longSL;
var TargetShortMath = shortMath;
var ShortSL = shortSL;
}
else if ((EURUSDYDaysClose > 0.7) && (EURUSDYDaysClose < 0.9))
{
TargetLongMath = longMath;
var LongSL = longSL;
var TargetShortMath = shortMath;
var ShortSL = shortSL;
}
//Round down the estimated profit target level, calculate target pips, round down target pips
var TargetLong = (Math.Round(TargetLongMath, 3));
var TargetPipslong = TargetLong - Symbol.Bid * Symbol.PipSize;
var TargetPipsLong = (Math.Round(TargetPipslong, 3));
//As above but for shorts
var TargetShort = (Math.Round(TargetShortMath, 3));
var TargetPipsshort = TargetShort - Symbol.Ask * Symbol.PipSize;
var TargetPipsShort = (Math.Round(TargetPipsshort, 3));
foreach (var position in Positions)
{
ClosePosition(position);
}
var risk = 0.95;
double Volume = (long)Math.Ceiling(Account.Equity / 100) * risk;
Volume = Symbol.NormalizeVolumeInUnits(Volume, RoundingMode.Down);
if (Volume > 100)
Volume = 100;
var SLBid = Math.Round(Symbol.Bid + longSL, 2);
var SLAsk = Math.Round(Symbol.Ask + shortSL, 2);
var TPBidProp = TargetPipsLong;
var TPBid = (Math.Round(TPBidProp * Symbol.PipSize, 2));
var TPAskProp = TargetPipsShort;
var TPAsk = (Math.Round(TPAskProp * Symbol.PipSize, 2));
PlaceStopOrder(TradeType.Buy, SymbolName, Volume, Symbol.Bid * Symbol.PipSize, "Buy", SLBid, TPBid);
PlaceStopOrder(TradeType.Sell, SymbolName, Volume, Symbol.Ask * Symbol.PipSize, "Sell", SLAsk, TPAsk);
}
}
}
}
That's all we can do here in forum, if you need more than this please ask a consultant to help you or post a job request.
@amusleh
amusleh
02 Apr 2021, 11:15
This sample might help you:
using cAlgo.API;
namespace cAlgo.Robots
{
[Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class PauseEvents : Robot
{
private bool _isPaused;
protected override void OnStart()
{
Chart.MouseDown += Chart_MouseDown;
}
private void Chart_MouseDown(ChartMouseEventArgs obj)
{
if (obj.ShiftKey)
{
_isPaused = true;
Print("Events paused");
}
else if (obj.CtrlKey)
{
_isPaused = false;
Print("Events running");
}
}
protected override void OnTick()
{
if (_isPaused) return;
}
protected override void OnBar()
{
if (_isPaused) return;
}
}
}
If you press shift + click then it will pause the OnTick/Bar, and if you press Ctrl + Click then it will allow the code on OnTick/Bar after is pause check to execute.
@amusleh
amusleh
01 Apr 2021, 12:38
RE: RE:
kotas24 said:
amusleh said:
Hi,
There is no such a feature right now, if you want not receive OnTick/Bar events then you can just set a Boolean flag based on your pause condition and ignore the events.
Thanks for the answer, but I don't want to lose these events, I want to wait for user action (e.g. mouse click on the chart) and then process onTick/Bar events
You don't have to, just use a boolean flag to disable/enable the events whenever you need.
@amusleh
amusleh
01 Apr 2021, 10:42
Hi,
This sample indicator might help you:
using cAlgo.API;
using cAlgo.API.Internals;
using System;
namespace cAlgo
{
/// <summary>
/// This sample indicator shows how to get a symbol data
/// </summary>
[Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class SymbolSample : Indicator
{
private TextBlock _spreadTextBlock;
private TextBlock _bidTextBlock;
private TextBlock _askTextBlock;
private TextBlock _unrealizedGrossProfitTextBlock;
private TextBlock _unrealizedNetProfitTextBlock;
private TextBlock _timeTillOpenTextBlock;
private TextBlock _timeTillCloseTextBlock;
private TextBlock _isOpenedTextBlock;
private Symbol _symbol;
[Parameter("Use Current Symbol", DefaultValue = true)]
public bool UseCurrentSymbol { get; set; }
[Parameter("Other Symbol Name", DefaultValue = "GBPUSD")]
public string OtherSymbolName { get; set; }
protected override void Initialize()
{
var grid = new Grid(23, 2)
{
BackgroundColor = Color.Gold,
Opacity = 0.6,
HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center,
};
var style = new Style();
style.Set(ControlProperty.Padding, 1);
style.Set(ControlProperty.Margin, 2);
style.Set(ControlProperty.FontWeight, FontWeight.Bold);
style.Set(ControlProperty.BackgroundColor, Color.Black);
_symbol = UseCurrentSymbol ? Symbol : Symbols.GetSymbol(OtherSymbolName);
grid.AddChild(new TextBlock { Text = "Symbol Info", Style = style, HorizontalAlignment = HorizontalAlignment.Center }, 0, 0, 1, 2);
grid.AddChild(new TextBlock { Text = "Name", Style = style }, 1, 0);
grid.AddChild(new TextBlock { Text = _symbol.Name, Style = style }, 1, 1);
grid.AddChild(new TextBlock { Text = "ID", Style = style }, 2, 0);
grid.AddChild(new TextBlock { Text = _symbol.Id.ToString(), Style = style }, 2, 1);
grid.AddChild(new TextBlock { Text = "Digits", Style = style }, 3, 0);
grid.AddChild(new TextBlock { Text = _symbol.Digits.ToString(), Style = style }, 3, 1);
grid.AddChild(new TextBlock { Text = "Description", Style = style }, 4, 0);
grid.AddChild(new TextBlock { Text = _symbol.Description, Style = style }, 4, 1);
grid.AddChild(new TextBlock { Text = "Lot Size", Style = style }, 5, 0);
grid.AddChild(new TextBlock { Text = _symbol.LotSize.ToString(), Style = style }, 5, 1);
grid.AddChild(new TextBlock { Text = "Pip Size", Style = style }, 6, 0);
grid.AddChild(new TextBlock { Text = _symbol.PipSize.ToString(), Style = style }, 6, 1);
grid.AddChild(new TextBlock { Text = "Pip Value", Style = style }, 7, 0);
grid.AddChild(new TextBlock { Text = _symbol.PipValue.ToString(), Style = style }, 7, 1);
grid.AddChild(new TextBlock { Text = "Tick Size", Style = style }, 8, 0);
grid.AddChild(new TextBlock { Text = _symbol.TickSize.ToString(), Style = style }, 8, 1);
grid.AddChild(new TextBlock { Text = "Tick Value", Style = style }, 9, 0);
grid.AddChild(new TextBlock { Text = _symbol.TickValue.ToString(), Style = style }, 9, 1);
grid.AddChild(new TextBlock { Text = "Volume In Units Max", Style = style }, 10, 0);
grid.AddChild(new TextBlock { Text = _symbol.VolumeInUnitsMax.ToString(), Style = style }, 10, 1);
grid.AddChild(new TextBlock { Text = "Volume In Units Min", Style = style }, 11, 0);
grid.AddChild(new TextBlock { Text = _symbol.VolumeInUnitsMin.ToString(), Style = style }, 11, 1);
grid.AddChild(new TextBlock { Text = "Volume In Units Step", Style = style }, 12, 0);
grid.AddChild(new TextBlock { Text = _symbol.VolumeInUnitsStep.ToString(), Style = style }, 12, 1);
grid.AddChild(new TextBlock { Text = "Ask", Style = style }, 13, 0);
_askTextBlock = new TextBlock { Text = _symbol.Ask.ToString(), Style = style };
grid.AddChild(_askTextBlock, 13, 1);
grid.AddChild(new TextBlock { Text = "Bid", Style = style }, 14, 0);
_bidTextBlock = new TextBlock { Text = _symbol.Bid.ToString(), Style = style };
grid.AddChild(_bidTextBlock, 14, 1);
grid.AddChild(new TextBlock { Text = "Spread", Style = style }, 15, 0);
_spreadTextBlock = new TextBlock { Text = _symbol.Spread.ToString(), Style = style };
grid.AddChild(_spreadTextBlock, 15, 1);
grid.AddChild(new TextBlock { Text = "Unrealized Gross Profit", Style = style }, 16, 0);
_unrealizedGrossProfitTextBlock = new TextBlock { Text = _symbol.UnrealizedGrossProfit.ToString(), Style = style };
grid.AddChild(_unrealizedGrossProfitTextBlock, 16, 1);
grid.AddChild(new TextBlock { Text = "Unrealized Net Profit", Style = style }, 17, 0);
_unrealizedNetProfitTextBlock = new TextBlock { Text = _symbol.UnrealizedNetProfit.ToString(), Style = style };
grid.AddChild(_unrealizedNetProfitTextBlock, 17, 1);
grid.AddChild(new TextBlock { Text = "Time Till Open", Style = style }, 18, 0);
_timeTillOpenTextBlock = new TextBlock { Text = _symbol.MarketHours.TimeTillOpen().ToString(), Style = style };
grid.AddChild(_timeTillOpenTextBlock, 18, 1);
grid.AddChild(new TextBlock { Text = "Time Till Close", Style = style }, 19, 0);
_timeTillCloseTextBlock = new TextBlock { Text = _symbol.MarketHours.TimeTillClose().ToString(), Style = style };
grid.AddChild(_timeTillCloseTextBlock, 19, 1);
grid.AddChild(new TextBlock { Text = "Is Opened", Style = style }, 20, 0);
_isOpenedTextBlock = new TextBlock { Text = _symbol.MarketHours.IsOpened().ToString(), Style = style };
grid.AddChild(_isOpenedTextBlock, 20, 1);
grid.AddChild(new TextBlock { Text = "Trading Sessions #", Style = style }, 21, 0);
grid.AddChild(new TextBlock { Text = _symbol.MarketHours.Sessions.Count.ToString(), Style = style }, 21, 1);
grid.AddChild(new TextBlock { Text = "Leverage Tier", Style = style }, 22, 0);
var leverageTiersStackPanel = new StackPanel
{
Orientation = Orientation.Horizontal
};
foreach (var leveragTier in _symbol.DynamicLeverage)
{
leverageTiersStackPanel.AddChild(new TextBlock { Text = string.Format("Leverage for volume up to {0} is {1}", leveragTier.Volume, leveragTier.Leverage), Style = style });
}
grid.AddChild(leverageTiersStackPanel, 22, 1);
Chart.AddControl(grid);
_symbol.Tick += Symbol_Tick;
Timer.Start(TimeSpan.FromSeconds(1));
}
private void Symbol_Tick(SymbolTickEventArgs obj)
{
_askTextBlock.Text = obj.Symbol.Ask.ToString();
_bidTextBlock.Text = obj.Symbol.Bid.ToString();
_spreadTextBlock.Text = obj.Symbol.Spread.ToString();
_unrealizedGrossProfitTextBlock.Text = obj.Symbol.UnrealizedGrossProfit.ToString();
_unrealizedNetProfitTextBlock.Text = obj.Symbol.UnrealizedNetProfit.ToString();
}
protected override void OnTimer()
{
_timeTillOpenTextBlock.Text = _symbol.MarketHours.TimeTillOpen().ToString();
_timeTillCloseTextBlock.Text = _symbol.MarketHours.TimeTillClose().ToString();
_isOpenedTextBlock.Text = _symbol.MarketHours.IsOpened().ToString();
}
public override void Calculate(int index)
{
}
}
}
Please read the API references for more info regarding symbols and bars.
@amusleh
amusleh
31 Mar 2021, 10:56
RE: RE:
yuval.ein said:
Is it panned for a future version? Is there a feature I can vote for? If not, hoe can I submit a feature request?
Thanks
You can open a thread on suggestions section, but your request is not that useful because when you back test you know how much data is available and there is no need to call load more history as all your backtest data will be loaded and no more or less, during live market condition its useful because you don't know the exact amount of available data so you can ask to load more if you need more data.
@amusleh
amusleh
31 Mar 2021, 09:22
Hi,
There is already several very good free session indicators, you can use those instead of building a new one.
Regarding your code, for adding multiple time zone function you have to use the "Application.UserTimeOffset" and "Application.UserTimeOffsetChanged" for getting user current time zone offset, and then you can convert your indicator Server.Time or bar open times to the user time zone offset by adding the time offset value.
And yes its possible to show a vertical text, you have to use StringBuilder and add each latter as a new line on it.
Getting user time offset example:
using cAlgo.API;
namespace cAlgo
{
/// <summary>
/// This sample indicator shows how to use the API Application object nad display its properties data inside a chart control
/// </summary>
[Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class ApplicationSample : Indicator
{
private TextBlock _userTimeOffsetTextBlock, _themeTextBlock;
[Parameter("Horizontal Alignment", DefaultValue = HorizontalAlignment.Center)]
public HorizontalAlignment HorizontalAlignment { get; set; }
[Parameter("Vertical Alignment", DefaultValue = VerticalAlignment.Center)]
public VerticalAlignment VerticalAlignment { get; set; }
protected override void Initialize()
{
Application.ColorThemeChanged += Application_ColorThemeChanged;
Application.UserTimeOffsetChanged += Application_UserTimeOffsetChanged;
DrawApplicationInfo();
}
private void Application_UserTimeOffsetChanged(UserTimeOffsetChangedEventArgs obj)
{
_userTimeOffsetTextBlock.Text = obj.UserTimeOffset.ToString();
}
private void Application_ColorThemeChanged(ColorThemeChangeEventArgs obj)
{
_themeTextBlock.Text = obj.ColorTheme.ToString();
}
private void DrawApplicationInfo()
{
var grid = new Grid(3, 2)
{
BackgroundColor = Color.Goldenrod,
HorizontalAlignment = HorizontalAlignment,
VerticalAlignment = VerticalAlignment
};
grid.AddChild(new TextBlock
{
Text = "Version",
Margin = 5
}, 0, 0);
grid.AddChild(new TextBlock
{
Text = Application.Version.ToString(),
Margin = 5
}, 0, 1);
grid.AddChild(new TextBlock
{
Text = "Theme",
Margin = 5
}, 1, 0);
_themeTextBlock = new TextBlock
{
Text = Application.ColorTheme.ToString(),
Margin = 5
};
grid.AddChild(_themeTextBlock, 1, 1);
grid.AddChild(new TextBlock
{
Text = "User Time Offset",
Margin = 5
}, 2, 0);
_userTimeOffsetTextBlock = new TextBlock
{
Text = Application.UserTimeOffset.ToString(),
Margin = 5
};
grid.AddChild(_userTimeOffsetTextBlock, 2, 1);
Chart.AddControl(grid);
}
public override void Calculate(int index)
{
}
}
}
Using StringBuilder:
using cAlgo.API;
using System.Text;
namespace cAlgo
{
/// <summary>
/// This sample shows how to use Chart.DrawStaticText method to draw static locked text on chart
/// </summary>
[Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class ChartStaticTextSample : Indicator
{
protected override void Initialize()
{
var stringBuilder = new StringBuilder();
stringBuilder.AppendLine("Symbol: " + SymbolName);
stringBuilder.AppendLine("TimeFrame: " + TimeFrame);
stringBuilder.AppendLine("Chart Type: " + Chart.ChartType);
Chart.DrawStaticText("Static_Sample", stringBuilder.ToString(), VerticalAlignment.Bottom, HorizontalAlignment.Left, Color.Red);
}
public override void Calculate(int index)
{
}
}
}
@amusleh
amusleh
31 Mar 2021, 09:16
RE: RE:
findsameh said:
Hello Ahmad,
Thanks for the suggestion. But with your suggested solution if you compare the result through the indicator code (Result[index]) and compare it to the result through the bot (crsi.Result[index]), you'd find that both values still don't match.
And I'm not sure why I'd need to change the indicator code to retrieve a value from indicator to bot, knowing the indicator already produces the correct values for CRSI.
Sameh
There was some issues in your indicator code, that causes issues when you use it on a cBot, like using invalid bar index.
I checked the indicator and cBot I posted and the results does match on backtest for EURUSD on Spotware cTrader beta.
@amusleh
amusleh
31 Mar 2021, 09:13
RE:
mpistorius said:
Hi Panagiotis,
This bug can be reproduced with the simplest of bots, and is still present in cTrader 4.0.
namespace cAlgo.Robots { [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)] public class Bug : Robot { protected override void OnStart() { var bars = MarketData.GetBars(TimeFrame.Hour4, "GBPUSD"); bars.BarOpened += Bars_BarOpened; } private void Bars_BarOpened(BarOpenedEventArgs obj) { Print("BarOpened called at {0}", Server.Time); } } }
The code above should only produce output on every 4 hour bar, but is executed on every tick instead. This is the log output:
30/03/2021 23:34:22.614 | cBot "Bug" was stopped for GBPUSD, h4.
30/03/2021 23:34:20.583 | BarOpened called at 30/03/2021 3:34:20 PM
30/03/2021 23:34:19.802 | BarOpened called at 30/03/2021 3:34:19 PM
30/03/2021 23:34:19.552 | BarOpened called at 30/03/2021 3:34:19 PM
30/03/2021 23:34:18.708 | BarOpened called at 30/03/2021 3:34:18 PM
30/03/2021 23:34:18.520 | BarOpened called at 30/03/2021 3:34:18 PM
30/03/2021 23:34:18.427 | BarOpened called at 30/03/2021 3:34:18 PM
30/03/2021 23:34:13.880 | BarOpened called at 30/03/2021 3:34:13 PM
30/03/2021 23:34:12.380 | BarOpened called at 30/03/2021 3:34:12 PM
30/03/2021 23:34:12.161 | BarOpened called at 30/03/2021 3:34:12 PM
30/03/2021 23:34:11.786 | BarOpened called at 30/03/2021 3:34:11 PM
30/03/2021 23:34:11.599 | BarOpened called at 30/03/2021 3:34:11 PM
30/03/2021 23:33:57.864 | cBot "Bug" was started successfully for GBPUSD, h4.
This doesn't happen in backtesting, only on a cbot running live. That fact makes it a particularly nasty surprise, which has already cost me real money.
Regards,
Morné
Hi,
Which broker cTrader you used for the test? I tried on Spotware Beta cTrader and I couldn't replicate the issue.
@amusleh
amusleh
06 Apr 2021, 11:23
Hi,
You can change date time to a numerical unit like Unix time and then use it instead of date time for your statistical models, as I know all time series data uses the date time for x coordinate.
@amusleh