Indicators in class outside Robot
Indicators in class outside Robot
20 Sep 2021, 21:19
Hi all,
I'm having trouble using an indicator in a separate class from the Robot (Main) class.
In the Robot class, I have the parameters and declarations for using an EMA, but since that class is separate from the other public class in which I wish to use the EMA Result, I get an error saying ''Error CS0103: The name 'TrendMA' does not exist in the current context".
I understand that this is because the EMA is local to the Main Robot class, though I'm having trouble calling the indicator into the class where I want to use it.
The short of my question is then: how can I call and declare an indicator in a class that is not the Main Robot class?
Please excuse my lack of code sample, the source for this bot is long, although I can provide it on request.
Thanks,
Replies
waym77
21 Sep 2021, 10:37
RE: RE:
firemyst said:
waym77 said:
Hi all,
I'm having trouble using an indicator in a separate class from the Robot (Main) class.
In the Robot class, I have the parameters and declarations for using an EMA, but since that class is separate from the other public class in which I wish to use the EMA Result, I get an error saying ''Error CS0103: The name 'TrendMA' does not exist in the current context".
I understand that this is because the EMA is local to the Main Robot class, though I'm having trouble calling the indicator into the class where I want to use it.
The short of my question is then: how can I call and declare an indicator in a class that is not the Main Robot class?
Please excuse my lack of code sample, the source for this bot is long, although I can provide it on request.
Thanks,
In short, without seeing any sample code posted of yours:
1) you need to "reference" the class. In the cTrader Automate section when you view your bot's source code, click on the triple-dot menu to manage references and make sure it's included
2) reference your TrendMA indicator similar to the following:
TrendMA _ma = Indicators.GetIndicator<TrendMA>(the list of parameters required);
Hi firemyst,
Thanks for the response, I appreciate it.
Your suggestion makes sense, referencing the indicator to the class, although I'm having trouble with the actual location.
I've attached the source code to show what I mean:
The main class (EZSUltimate) contains the parameters and the OnStart method which is where indicators normally go.
I would like to use those three EMAs in the TradingPanel class, specifically in the Calc_SL() method.
Thanks for your help.
using System;
using System.Collections.Generic;
using cAlgo.API;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
namespace cAlgo.Robots
{
[Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class EZSUltimate : Robot
{
[Parameter("Vertical Position", Group = "Panel alignment", DefaultValue = VerticalAlignment.Top)]
public VerticalAlignment PanelVerticalAlignment { get; set; }
[Parameter("Horizontal Position", Group = "Panel alignment", DefaultValue = HorizontalAlignment.Left)]
public HorizontalAlignment PanelHorizontalAlignment { get; set; }
[Parameter("Default Price", Group = "Default trade parameters", DefaultValue = 1.0)]
public double DefaultPrice { get; set; }
[Parameter("Default Lots", Group = "Default trade parameters", DefaultValue = 0.01)]
public double DefaultLots { get; set; }
[Parameter("Default Risk", Group = "Default trade parameters", DefaultValue = 1.0)]
public double DefaultRisk { get; set; }
[Parameter("Default Fragmentation", Group = "Default trade parameters", DefaultValue = 1)]
public double DefaultFrag { get; set; }
[Parameter("Default Take Profit (pips)", Group = "Default trade parameters", DefaultValue = 10)]
public double DefaultTakeProfitPips { get; set; }
[Parameter("Default Stop Loss (pips)", Group = "Default trade parameters", DefaultValue = 10)]
public double DefaultStopLossPips { get; set; }
[Parameter("Moving Average Type", Group = "MA", DefaultValue = MovingAverageType.Simple)]
public MovingAverageType MAType { get; set; }
[Parameter("Fast MA Periods", Group = "MA", DefaultValue = 21, MinValue = 1, MaxValue = 500)]
public int FastMAPeriods { get; set; }
[Parameter("Slow MA Periods", Group = "MA", DefaultValue = 50, MinValue = 1, MaxValue = 1000)]
public int SlowMAPeriods { get; set; }
[Parameter("Trend MA Periods", Group = "MA", DefaultValue = 200, MinValue = 1, MaxValue = 1500)]
public int TrendMAPeriods { get; set; }
MovingAverage FastMA;
MovingAverage SlowMA;
MovingAverage TrendMA;
protected override void OnStart()
{
var tradingPanel = new TradingPanel(this, Symbol, DefaultPrice, DefaultFrag, DefaultLots, DefaultRisk, DefaultStopLossPips, DefaultTakeProfitPips);
FastMA = Indicators.MovingAverage(Bars.ClosePrices, FastMAPeriods, MAType);
SlowMA = Indicators.MovingAverage(Bars.ClosePrices, SlowMAPeriods, MAType);
TrendMA = Indicators.MovingAverage(Bars.ClosePrices, TrendMAPeriods, MAType);
var border = new Border
{
VerticalAlignment = PanelVerticalAlignment,
HorizontalAlignment = PanelHorizontalAlignment,
Style = Styles.CreatePanelBackgroundStyle(),
Margin = "20 40 20 20",
Width = 225,
Child = tradingPanel
};
Chart.AddControl(border);
}
}
public class TradingPanel : CustomControl
{
private const string RiskInputKey = "RiskKey";
private const string LotsInputKey = "LotsKey";
private const string SuggestedInputKey = "SuggestedKey";
private const string PriceInputKey = "PriceKey";
private const string FragInputKey = "FragKey";
private const string TakeProfitInputKey = "TPKey";
private const string StopLossInputKey = "SLKey";
private readonly IDictionary<string, TextBox> _inputMap = new Dictionary<string, TextBox>();
private readonly Robot _robot;
private readonly Symbol _symbol;
public TradingPanel(Robot robot, Symbol symbol, double defaultPrice, double defaultFrag, double defaultLots, double defaultRisk, double defaultStopLossPips, double defaultTakeProfitPips)
{
_robot = robot;
_symbol = symbol;
AddChild(CreateTradingPanel(defaultPrice, defaultFrag, defaultLots, defaultRisk, defaultStopLossPips, defaultTakeProfitPips));
}
private ControlBase CreateTradingPanel(double defaultPrice, double defaultFrag, double defaultLots, double defaultRisk, double defaultStopLossPips, double defaultTakeProfitPips)
{
var mainPanel = new StackPanel();
var header = CreateHeader();
mainPanel.AddChild(header);
var contentPanel = CreateContentPanel(defaultPrice, defaultFrag, defaultLots, defaultRisk, defaultStopLossPips, defaultTakeProfitPips);
mainPanel.AddChild(contentPanel);
return mainPanel;
}
private ControlBase CreateHeader()
{
var headerBorder = new Border
{
BorderThickness = "0 0 0 1",
Style = Styles.CreateCommonBorderStyle()
};
var header = new TextBlock
{
Text = "Quick Trading Panel",
Margin = "10 7",
Style = Styles.CreateHeaderStyle()
};
headerBorder.Child = header;
return headerBorder;
}
private StackPanel CreateContentPanel(double defaultPrice, double defaultFrag, double defaultLots, double defaultRisk, double defaultStopLossPips, double defaultTakeProfitPips)
{
var contentPanel = new StackPanel
{
Margin = 9
};
var grid = new Grid(9, 3);
grid.Columns[1].SetWidthInPixels(5);
var sellmarketButton = CreateMarketTradeButton("MARKET SELL", Styles.CreateSellButtonStyle(), TradeType.Sell);
grid.AddChild(sellmarketButton, 0, 0);
var buymarketButton = CreateMarketTradeButton("MARKET BUY", Styles.CreateBuyButtonStyle(), TradeType.Buy);
grid.AddChild(buymarketButton, 0, 2);
var sellstopButton = CreateStopTradeButton("SELL STOP", Styles.CreateSellButtonStyle(), TradeType.Sell);
grid.AddChild(sellstopButton, 1, 0);
var buystopButton = CreateStopTradeButton("BUY STOP", Styles.CreateBuyButtonStyle(), TradeType.Buy);
grid.AddChild(buystopButton, 1, 2);
var selllimitButton = CreateLimitTradeButton("SELL LIMIT", Styles.CreateSellButtonStyle(), TradeType.Sell);
grid.AddChild(selllimitButton, 3, 0);
var buylimitButton = CreateLimitTradeButton("BUY LIMIT", Styles.CreateBuyButtonStyle(), TradeType.Buy);
grid.AddChild(buylimitButton, 3, 2);
var priceInput = CreateInputWithLabel("Pending Price", defaultPrice.ToString("F2"), PriceInputKey);
grid.AddChild(priceInput, 4, 0);
var fragInput = CreateInputWithLabel("Fragmentation", defaultFrag.ToString("F2"), FragInputKey);
grid.AddChild(fragInput, 4, 2);
var riskInput = CreateInputWithLabel("Risk %", defaultRisk.ToString("F2"), RiskInputKey);
grid.AddChild(riskInput, 5, 0, 1, 3);
var takeProfitInput = CreateInputWithLabel("Take Profit (Pips)", defaultTakeProfitPips.ToString("F1"), TakeProfitInputKey);
grid.AddChild(takeProfitInput, 6, 0, 1, 3);
var closeAllPendingButton = CreateCloseAllPendingButton();
grid.AddChild(closeAllPendingButton, 7, 0, 1, 3);
var closeAllOpenButton = CreateCloseAllOpenButton();
grid.AddChild(closeAllOpenButton, 8, 0, 1, 3);
contentPanel.AddChild(grid);
return contentPanel;
}
private Button CreateMarketTradeButton(string text, Style style, TradeType tradeType)
{
var tradeButton = new Button
{
Text = text,
Style = style,
Height = 25
};
tradeButton.Click += args => PlaceMarket(tradeType);
return tradeButton;
}
private Button CreateStopTradeButton(string text, Style style, TradeType tradeType)
{
var tradeButton = new Button
{
Text = text,
Style = style,
Height = 25
};
tradeButton.Click += args => PlaceStop(tradeType);
return tradeButton;
}
private Button CreateLimitTradeButton(string text, Style style, TradeType tradeType)
{
var tradeButton = new Button
{
Text = text,
Style = style,
Height = 25
};
tradeButton.Click += args => PlaceLimit(tradeType);
return tradeButton;
}
private ControlBase CreateCloseAllPendingButton()
{
var closeAllBorder = new Border
{
Margin = "0 10 0 0",
BorderThickness = "0 1 0 0",
Style = Styles.CreateCommonBorderStyle()
};
var closeButton = new Button
{
Style = Styles.CreateCloseButtonStyle(),
Text = "Close All Pending",
Margin = "0 10 0 0"
};
closeButton.Click += args => CloseAllPending();
closeAllBorder.Child = closeButton;
return closeAllBorder;
}
private ControlBase CreateCloseAllOpenButton()
{
var closeAllBorder = new Border
{
Margin = "0 10 0 0",
BorderThickness = "0 1 0 0",
Style = Styles.CreateCommonBorderStyle()
};
var closeButton = new Button
{
Style = Styles.CreateCloseButtonStyle(),
Text = "Close All Open",
Margin = "0 10 0 0"
};
closeButton.Click += args => CloseAllOpen();
closeAllBorder.Child = closeButton;
return closeAllBorder;
}
private Panel CreateInputWithLabel(string label, string defaultValue, string inputKey)
{
var stackPanel = new StackPanel
{
Orientation = Orientation.Vertical,
Margin = "0 10 0 0"
};
var textBlock = new TextBlock
{
Text = label
};
var input = new TextBox
{
Margin = "0 5 0 0",
Text = defaultValue,
Style = Styles.CreateInputStyle()
};
_inputMap.Add(inputKey, input);
stackPanel.AddChild(textBlock);
stackPanel.AddChild(input);
return stackPanel;
}
private void PlaceMarket(TradeType tradeType)
{
var _vol_usable = 0.0;
var _frag = GetValueFromInput(FragInputKey, 0);
if (_frag >= 1)
{
_vol_usable = Calc_UPT();
var stopLossPips = Calc_SL();
var takeProfitPips = GetValueFromInput(TakeProfitInputKey, 0);
var _price_usable = GetValueFromInput(PriceInputKey, 0);
if (_vol_usable <= 0)
{
_robot.Print(string.Format("{0} failed, invalid Lots", tradeType));
return;
}
for (int i = 0; i < _frag; i++)
{
_robot.ExecuteMarketOrderAsync(tradeType, _symbol.Name, _vol_usable, string.Empty, stopLossPips, takeProfitPips);
}
}
else if (_frag < 1)
{
_robot.Print(string.Format("{0} failed, invalid Frag", tradeType));
return;
}
}
private void PlaceStop(TradeType tradeType)
{
var _vol_usable = 0.0;
var _frag = GetValueFromInput(FragInputKey, 0);
if (_frag >= 1)
{
_vol_usable = Calc_UPT();
var stopLossPips = Calc_SL();
var takeProfitPips = GetValueFromInput(TakeProfitInputKey, 0);
var _price_usable = GetValueFromInput(PriceInputKey, 0);
if (_vol_usable <= 0)
{
_robot.Print(string.Format("{0} failed, invalid Lots", tradeType));
return;
}
for (int i = 0; i < _frag; i++)
{
_robot.PlaceStopOrderAsync(tradeType, _symbol.Name, _vol_usable, _price_usable, string.Empty, stopLossPips, takeProfitPips, null);
}
}
else if (_frag < 1)
{
_robot.Print(string.Format("{0} failed, invalid Frag", tradeType));
return;
}
}
private void PlaceLimit(TradeType tradeType)
{
var _vol_usable = 0.0;
var _frag = GetValueFromInput(FragInputKey, 0);
if (_frag >= 1)
{
_vol_usable = Calc_UPT();
var stopLossPips = Calc_SL();
var takeProfitPips = GetValueFromInput(TakeProfitInputKey, 0);
var _price_usable = GetValueFromInput(PriceInputKey, 0);
if (_vol_usable <= 0)
{
_robot.Print(string.Format("{0} failed, invalid Lots", tradeType));
return;
}
for (int i = 0; i < _frag; i++)
{
_robot.PlaceLimitOrderAsync(tradeType, _symbol.Name, _vol_usable, _price_usable, string.Empty, stopLossPips, takeProfitPips, null);
}
}
else if (_frag < 1)
{
_robot.Print(string.Format("{0} failed, invalid Frag", tradeType));
return;
}
}
private double Calc_UPT()
{
var _frag = GetValueFromInput(FragInputKey, 0);
var _RiskPercent = GetValueFromInput(RiskInputKey, 0);
var _SL = GetValueFromInput(StopLossInputKey, 0);
double costPerPip = (double)((int)(_robot.Symbol.PipValue * 10000000)) / 100;
double baseNumber = _robot.Account.Balance;
double sizeInLots = Math.Round((baseNumber * _RiskPercent / 100) / (_SL * costPerPip), 2);
var result = _robot.Symbol.QuantityToVolumeInUnits(sizeInLots);
if (result > _robot.Symbol.VolumeInUnitsMax)
{
result = _robot.Symbol.VolumeInUnitsMax;
}
else if (result < _robot.Symbol.VolumeInUnitsMin)
{
result = _robot.Symbol.VolumeInUnitsMin;
}
else if (result % _robot.Symbol.VolumeInUnitsStep != 0)
{
result = result - (result % _robot.Symbol.VolumeInUnitsStep);
}
var _units = Math.Round(result / _frag, 2);
return _units;
}
private double Calc_SL()
{
var _FromInput = GetValueFromInput(StopLossInputKey, 0);
var _Price = (_robot.Symbol.Bid + _robot.Symbol.Ask) / 2;
var _BarsHL = 0.0;
var _Distance = 0.0;
var trend = _robot.Bars.ClosePrices.LastValue > TrendMA.Result.LastValue ? true : false;
var fast = FastMA.Result.LastValue > SlowMA.Result.LastValue ? true : false;
if (trend && fast)
{
_BarsHL = _robot.Bars.LowPrices.LastValue;
_Distance = (_Price - _BarsHL) * _robot.Symbol.PipSize;
}
else if (!trend && !fast)
{
_BarsHL = _robot.Bars.HighPrices.LastValue;
_Distance = (_BarsHL - _Price) * _robot.Symbol.PipSize;
}
return _Distance;
}
private double GetValueFromInput(string inputKey, double defaultValue)
{
double value;
return double.TryParse(_inputMap[inputKey].Text, out value) ? value : defaultValue;
}
private void CloseAllPending()
{
foreach (var pending in _robot.PendingOrders)
_robot.CancelPendingOrderAsync(pending);
}
private void CloseAllOpen()
{
foreach (var position in _robot.Positions)
_robot.ClosePositionAsync(position);
}
}
public static class Styles
{
public static Style CreatePanelBackgroundStyle()
{
var style = new Style();
style.Set(ControlProperty.CornerRadius, 3);
style.Set(ControlProperty.BackgroundColor, GetColorWithOpacity(Color.FromHex("#292929"), 0.85m), ControlState.DarkTheme);
style.Set(ControlProperty.BackgroundColor, GetColorWithOpacity(Color.FromHex("#FFFFFF"), 0.85m), ControlState.LightTheme);
style.Set(ControlProperty.BorderColor, Color.FromHex("#3C3C3C"), ControlState.DarkTheme);
style.Set(ControlProperty.BorderColor, Color.FromHex("#C3C3C3"), ControlState.LightTheme);
style.Set(ControlProperty.BorderThickness, new Thickness(1));
return style;
}
public static Style CreateCommonBorderStyle()
{
var style = new Style();
style.Set(ControlProperty.BorderColor, GetColorWithOpacity(Color.FromHex("#FFFFFF"), 0.12m), ControlState.DarkTheme);
style.Set(ControlProperty.BorderColor, GetColorWithOpacity(Color.FromHex("#000000"), 0.12m), ControlState.LightTheme);
return style;
}
public static Style CreateHeaderStyle()
{
var style = new Style();
style.Set(ControlProperty.ForegroundColor, GetColorWithOpacity("#FFFFFF", 0.70m), ControlState.DarkTheme);
style.Set(ControlProperty.ForegroundColor, GetColorWithOpacity("#000000", 0.65m), ControlState.LightTheme);
return style;
}
public static Style CreateInputStyle()
{
var style = new Style(DefaultStyles.TextBoxStyle);
style.Set(ControlProperty.BackgroundColor, Color.FromHex("#1A1A1A"), ControlState.DarkTheme);
style.Set(ControlProperty.BackgroundColor, Color.FromHex("#111111"), ControlState.DarkTheme | ControlState.Hover);
style.Set(ControlProperty.BackgroundColor, Color.FromHex("#E7EBED"), ControlState.LightTheme);
style.Set(ControlProperty.BackgroundColor, Color.FromHex("#D6DADC"), ControlState.LightTheme | ControlState.Hover);
style.Set(ControlProperty.CornerRadius, 3);
return style;
}
public static Style CreateBuyButtonStyle()
{
return CreateButtonStyle(Color.FromHex("#009345"), Color.FromHex("#10A651"));
}
public static Style CreateSellButtonStyle()
{
return CreateButtonStyle(Color.FromHex("#F05824"), Color.FromHex("#FF6C36"));
}
public static Style CreateCloseButtonStyle()
{
return CreateButtonStyle(Color.FromHex("#F05824"), Color.FromHex("#FF6C36"));
}
private static Style CreateButtonStyle(Color color, Color hoverColor)
{
var style = new Style(DefaultStyles.ButtonStyle);
style.Set(ControlProperty.BackgroundColor, color, ControlState.DarkTheme);
style.Set(ControlProperty.BackgroundColor, color, ControlState.LightTheme);
style.Set(ControlProperty.BackgroundColor, hoverColor, ControlState.DarkTheme | ControlState.Hover);
style.Set(ControlProperty.BackgroundColor, hoverColor, ControlState.LightTheme | ControlState.Hover);
style.Set(ControlProperty.ForegroundColor, Color.FromHex("#FFFFFF"), ControlState.DarkTheme);
style.Set(ControlProperty.ForegroundColor, Color.FromHex("#FFFFFF"), ControlState.LightTheme);
return style;
}
private static Color GetColorWithOpacity(Color baseColor, decimal opacity)
{
var alpha = (int)Math.Round(byte.MaxValue * opacity, MidpointRounding.AwayFromZero);
return Color.FromArgb(alpha, baseColor);
}
}
}
@waym77
waym77
22 Sep 2021, 09:56
RE: RE: RE: RE:
firemyst said:
Have you tried passing in the MA objects in the "constructor" to your TradingPanel inner class?
You'll have to create the Constructor with the appropriate parameters.
Hi there, forgive me, I am not very familiar with constructor arguments.
Would it look something like below?
public TradingPanel(MovingAverage TrendMA, Robot robot, Symbol symbol, double defaultPrice, double defaultFrag, double defaultLots, double defaultRisk, double defaultStopLossPips, double defaultTakeProfitPips)
{
TrendMA = Indicators.MovingAverage(Bars.ClosePrices, TrendPeriods, MovingAverageType.Exponential);
_robot = robot;
_symbol = symbol;
AddChild(CreateTradingPanel(defaultPrice, defaultFrag, defaultLots, defaultRisk, defaultStopLossPips, defaultTakeProfitPips));
}
I understand I'll also have to create new parameters for values like TrendPeriods in this class.
Thanks,
@waym77
firemyst
22 Sep 2021, 10:17
RE: RE: RE: RE: RE:
waym77 said:
firemyst said:
Have you tried passing in the MA objects in the "constructor" to your TradingPanel inner class?
You'll have to create the Constructor with the appropriate parameters.
Hi there, forgive me, I am not very familiar with constructor arguments.
Would it look something like below?
public TradingPanel(MovingAverage TrendMA, Robot robot, Symbol symbol, double defaultPrice, double defaultFrag, double defaultLots, double defaultRisk, double defaultStopLossPips, double defaultTakeProfitPips) { TrendMA = Indicators.MovingAverage(Bars.ClosePrices, TrendPeriods, MovingAverageType.Exponential); _robot = robot; _symbol = symbol; AddChild(CreateTradingPanel(defaultPrice, defaultFrag, defaultLots, defaultRisk, defaultStopLossPips, defaultTakeProfitPips)); }
I understand I'll also have to create new parameters for values like TrendPeriods in this class.
Thanks,
For your constructor, you would just have something similar to the following:
//In your other outer class, create the MA object as you normally would in the OnStart method;
//then after all the MA's are created, put in your
var tradingPanel = new TradingPanel(TrendMA, this, Symbol, ...);
//Now alter your TradingPanel class similar to the following.
public class TradingPanel : CustomControl
{
private MovingAverage _trendMA;
//All classes I believe have to have the default constructor
public TradingPanel() {}
public TrandingPanel(MovingAverage TrendMA, Robot r, Symbol s, ... )
{
_trendMA = TrendMA;
_robot = r;
_symbol = s;
// etc etc etc
}
}
If you can't get the above to work or it doesn't recognize the MovingAverage object declaration in the TradingPanel class, then that class probably can't reference the MovingAverage object, and you may have to ask @Panagiotis to lend his expert knowledge.
@firemyst
firemyst
21 Sep 2021, 03:30
RE:
waym77 said:
In short, without seeing any sample code posted of yours:
1) you need to "reference" the class. In the cTrader Automate section when you view your bot's source code, click on the triple-dot menu to manage references and make sure it's included
2) reference your TrendMA indicator similar to the following:
TrendMA _ma = Indicators.GetIndicator<TrendMA>(the list of parameters required);
@firemyst