
Topics
Replies
whis.gg
15 Dec 2016, 17:12
Hi Andi. There isn't anything wrong with different count values. I advice you to write an indicator ploting multiple timeframe Moving Averages into one chart so you will understand the logic. /forum/whats-new/1463
@whis.gg
whis.gg
15 Dec 2016, 01:03
Here you go.
using System; using cAlgo.API; using cAlgo.API.Internals; using cAlgo.API.Indicators; namespace cAlgo { [Indicator("DMS", IsOverlay = false, ScalePrecision = 0, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)] public class DirectionalMovementSystem : Indicator { [Parameter("Period", DefaultValue = 14, MinValue = 1)] public int Period { get; set; } [Parameter("MA Type", DefaultValue = MovingAverageType.WilderSmoothing)] public MovingAverageType MaType { get; set; } [Parameter("ADXR", DefaultValue = 14, MinValue = 0)] public int AdxrPeriod { get; set; } [Output("ADX", Color = Colors.Cyan)] public IndicatorDataSeries ADX { get; set; } [Output("ADXR", Color = Colors.Yellow)] public IndicatorDataSeries ADXR { get; set; } [Output("DI+", Color = Colors.Green)] public IndicatorDataSeries DiPlus { get; set; } [Output("Di-", Color = Colors.Red)] public IndicatorDataSeries DiMinus { get; set; } private DataSeries high, low, close; private IndicatorDataSeries tr, dmPlus, dmMinus, adx; private MovingAverage maTr, maDmPlus, maDmMinus, maAdx; protected override void Initialize() { high = MarketSeries.High; low = MarketSeries.Low; close = MarketSeries.Close; tr = CreateDataSeries(); dmPlus = CreateDataSeries(); dmMinus = CreateDataSeries(); adx = CreateDataSeries(); maTr = Indicators.MovingAverage(tr, Period, MaType); maDmPlus = Indicators.MovingAverage(dmPlus, Period, MaType); maDmMinus = Indicators.MovingAverage(dmMinus, Period, MaType); maAdx = Indicators.MovingAverage(adx, Period, MaType); } public override void Calculate(int index) { if (index == 0) { tr[0] = high[0] - low[0]; dmPlus[0] = 0; dmMinus[0] = 0; } else { tr[index] = Math.Max(Math.Abs(low[index] - close[index - 1]), Math.Max(Math.Abs(high[index] - close[index - 1]), high[index] - low[index])); dmPlus[index] = high[index] - high[index - 1] > low[index - 1] - low[index] ? Math.Max(high[index] - high[index - 1], 0) : 0; dmMinus[index] = low[index - 1] - low[index] > high[index] - high[index - 1] ? Math.Max(low[index - 1] - low[index], 0) : 0; DiPlus[index] = 100 * (maTr.Result[index] == 0 ? 0 : maDmPlus.Result[index] / maTr.Result[index]); DiMinus[index] = 100 * (maTr.Result[index] == 0 ? 0 : maDmMinus.Result[index] / maTr.Result[index]); adx[index] = Math.Abs((DiPlus[index] - DiMinus[index]) / (DiPlus[index] + DiMinus[index])); ADX[index] = adx[index] == 0 ? 50 : 100 * maAdx.Result[index]; ADXR[index] = (ADX[index] + ADX[index - AdxrPeriod]) / 2; } } } }
@whis.gg
whis.gg
28 Nov 2016, 12:18
Hi, you need to write a method that's called on each new bar. See sample below.
using cAlgo.API; namespace cAlgo { [Indicator(IsOverlay = false, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)] public class NewIndicator : Indicator { private int lastIndex = 0; public override void Calculate(int index) { if (index > lastIndex) { OnBarClosed(lastIndex); lastIndex = index; } } private void OnBarClosed(int index) { // Put your logic here } } }
@whis.gg
whis.gg
20 Nov 2016, 16:10
You should ask Spotware not me. All I am just saying is the fact that the name showed on the chart must be constant value and values in parentheses are inputed paramater values.
You can print whatever you want on the chart as text object with static position.
ChartObjects.DrawText("objectName", "COTReport(British Pound)", StaticPosition.TopLeft, Colors.Black);
@whis.gg
whis.gg
19 Nov 2016, 15:35
Hi, the indicator name must be constant value so it's not possible to change in runtime. By default it shows indicator name and its parameters in parentheses, therefore if the Period is a parameter then it should be printed on the chart as desired.
using cAlgo.API; using cAlgo.API.Indicators; namespace cAlgo { [Levels(30, 70)] [Indicator("RSI", IsOverlay = false, ScalePrecision = 0, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)] public class RSI : Indicator { [Parameter(DefaultValue = 14, MinValue = 1)] public int Period { get; set; } [Output("Main")] public IndicatorDataSeries Result { get; set; } private RelativeStrengthIndex rsi; protected override void Initialize() { rsi = Indicators.RelativeStrengthIndex(MarketSeries.Close, Period); } public override void Calculate(int index) { Result[index] = rsi.Result[index]; } } }
@whis.gg
whis.gg
19 Nov 2016, 14:01
Hi, you need set access rights in the indicator attribute. See the sample below.
[Indicator(AccessRights = AccessRights.Internet)] public class SampleIndicator : Indicator
@whis.gg
whis.gg
18 Nov 2016, 18:02
Hi, there isn't built-in function called on each bar except from the market series of the chart that you can override. However, you can write your own function for each series.
using cAlgo.API; using cAlgo.API.Internals; namespace cAlgo { [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)] public class OnBar : Robot { private MarketSeries seriesMinute1, seriesMinute15, seriesMinute30; private int lastIndexMinute1, lastIndexMinute15, lastIndexMinute30; protected override void OnStart() { seriesMinute1 = MarketData.GetSeries(TimeFrame.Minute); seriesMinute15 = MarketData.GetSeries(TimeFrame.Minute15); seriesMinute30 = MarketData.GetSeries(TimeFrame.Minute15); } protected override void OnTick() { int currentIndexMinute1 = seriesMinute1.Open.Count - 1; int currentIndexMinute15 = seriesMinute15.Open.Count - 1; int currentIndexMinute30 = seriesMinute30.Open.Count - 1; if (currentIndexMinute1 > lastIndexMinute1) { OnBarMinute1(currentIndexMinute1); lastIndexMinute1 = currentIndexMinute1; } if (currentIndexMinute15 > lastIndexMinute15) { OnBarMinute15(currentIndexMinute15); lastIndexMinute15 = currentIndexMinute15; } if (currentIndexMinute30 > lastIndexMinute30) { OnBarMinute30(currentIndexMinute30); lastIndexMinute30 = currentIndexMinute30; } } private void OnBarMinute1(int index) { // Called on each new bar of Minute1 dataseries } private void OnBarMinute15(int index) { // Called on each new bar of Minute15 dataseries } private void OnBarMinute30(int index) { // Called on each new bar of Minute30 dataseries } } }
@whis.gg
whis.gg
15 Nov 2016, 00:38
Hi, Directional Movement System in cTrader platform is using Wilder Smoothing that can't be changed. I have re-built the indicator with an option to choose different smoothing methods. Build the indicator and change MA Type to Exponential, it should match the MT4 results.
using System; using cAlgo.API; using cAlgo.API.Internals; using cAlgo.API.Indicators; namespace cAlgo { [Indicator("DMS", IsOverlay = false, ScalePrecision = 0, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)] public class DirectionalMovementSystem : Indicator { [Parameter("Period", DefaultValue = 14, MinValue = 1)] public int Period { get; set; } [Parameter("MA Type", DefaultValue = MovingAverageType.WilderSmoothing)] public MovingAverageType MaType { get; set; } [Output("ADX", Color = Colors.Cyan)] public IndicatorDataSeries ADX { get; set; } [Output("DI+", Color = Colors.Green)] public IndicatorDataSeries DiPlus { get; set; } [Output("Di-", Color = Colors.Red)] public IndicatorDataSeries DiMinus { get; set; } private DataSeries high, low, close; private IndicatorDataSeries tr, dmPlus, dmMinus, adx; private MovingAverage maTr, maDmPlus, maDmMinus, maAdx; protected override void Initialize() { high = MarketSeries.High; low = MarketSeries.Low; close = MarketSeries.Close; tr = CreateDataSeries(); dmPlus = CreateDataSeries(); dmMinus = CreateDataSeries(); adx = CreateDataSeries(); maTr = Indicators.MovingAverage(tr, Period, MaType); maDmPlus = Indicators.MovingAverage(dmPlus, Period, MaType); maDmMinus = Indicators.MovingAverage(dmMinus, Period, MaType); maAdx = Indicators.MovingAverage(adx, Period, MaType); } public override void Calculate(int index) { if (index == 0) { tr[0] = high[0] - low[0]; dmPlus[0] = 0; dmMinus[0] = 0; } else { tr[index] = Math.Max(Math.Abs(low[index] - close[index - 1]), Math.Max(Math.Abs(high[index] - close[index - 1]), high[index] - low[index])); dmPlus[index] = high[index] - high[index - 1] > low[index - 1] - low[index] ? Math.Max(high[index] - high[index - 1], 0) : 0; dmMinus[index] = low[index - 1] - low[index] > high[index] - high[index - 1] ? Math.Max(low[index - 1] - low[index], 0) : 0; DiPlus[index] = 100 * (maTr.Result[index] == 0 ? 0 : maDmPlus.Result[index] / maTr.Result[index]); DiMinus[index] = 100 * (maTr.Result[index] == 0 ? 0 : maDmMinus.Result[index] / maTr.Result[index]); adx[index] = Math.Abs((DiPlus[index] - DiMinus[index]) / (DiPlus[index] + DiMinus[index])); ADX[index] = adx[index] == 0 ? 50 : 100 * maAdx.Result[index]; } } } }
@whis.gg
whis.gg
09 Nov 2016, 21:12
Try following code. It's checking symbol code instead of label so you don't have to set different label for each instance to make them work seperatly.
using System.Linq; using cAlgo.API; using cAlgo.API.Internals; namespace cAlgo { [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)] public class AlcaideSR : Robot { [Parameter("Volume", DefaultValue = 1000)] public int Volume { get; set; } [Parameter("Pips away", DefaultValue = 20)] public int PipsAway { get; set; } [Parameter("TP", DefaultValue = 60)] public int TakeProfitPips { get; set; } [Parameter("SL", DefaultValue = 20)] public int StopLossPips { get; set; } [Parameter("Label", DefaultValue = "Rich")] public string Label { get; set; } [Parameter("Buy ?", DefaultValue = true)] public bool IsBuy { get; set; } protected override void OnStart() { if (Positions.Where(pos => pos.SymbolCode == Symbol.Code).Count() == 0) { if (IsBuy) { double targetPrice = Symbol.Ask - PipsAway * Symbol.PipSize; PlaceLimitOrder(TradeType.Buy, Symbol, Volume, targetPrice, Label, StopLossPips, TakeProfitPips); } else { double targetPrice = Symbol.Bid + PipsAway * Symbol.PipSize; PlaceLimitOrder(TradeType.Sell, Symbol, Volume, targetPrice, Label, StopLossPips, TakeProfitPips); } } Positions.Opened += OnPositionOpened; } private void OnPositionOpened(PositionOpenedEventArgs obj) { if (obj.Position.SymbolCode == Symbol.Code) { if (obj.Position.TradeType == TradeType.Buy) { double targetPrice = Symbol.Bid - PipsAway * Symbol.PipSize; PlaceStopOrder(TradeType.Sell, Symbol, Volume, targetPrice, Label, StopLossPips, TakeProfitPips); } else { double targetPrice = Symbol.Ask + PipsAway * Symbol.PipSize; PlaceStopOrder(TradeType.Buy, Symbol, Volume, targetPrice, Label, StopLossPips, TakeProfitPips); } } } } }
@whis.gg
whis.gg
09 Nov 2016, 14:37
Positions is collection of all opened positions of the trading account. You might be using different labels for each instance but you are still working with the collection containing all trades. Add condition that checks if opened position label is equal to your instance label or make new collection inside cBot memory and handle positions from there.
@whis.gg
whis.gg
09 Nov 2016, 00:33
If you need collection of historical trades (closed positions) you can do following.
using System.Collections.Generic; using System.Linq; using cAlgo.API; namespace cAlgo { [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)] public class CollectionOfPositions : Robot { private List<Position> openedPositions = new List<Position>(); private List<HistoricalTrade> closedPositions = new List<HistoricalTrade>(); protected override void OnStart() { Positions.Closed += OnPositionClosed; } private void OnPositionClosed(PositionClosedEventArgs obj) { if (openedPositions.Contains(obj.Position)) { openedPositions.Remove(obj.Position); closedPositions.Add(History.First(x => x.PositionId == obj.Position.Id)); } } protected override void OnBar() { if (true) { TradeResult result = ExecuteMarketOrder(TradeType.Sell, Symbol, 1000); if (result.IsSuccessful) { openedPositions.Add(result.Position); } } bool allPositionsClosed = openedPositions.Count() == 0 ? true : false; } } }
@whis.gg
whis.gg
09 Nov 2016, 00:19
Currently opened positions "Positions" and historical trades "History" are two different collections of objects. You can't compare them like that, compare Position.ID and HistoricalTrade.PositionId. Personally I would create collection of positions hold in cBot memory, adding and removing positions during the process so you can handle them easily, see sample below.
using System.Collections.Generic; using System.Linq; using cAlgo.API; namespace cAlgo { [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)] public class CollectionOfPositions : Robot { private List<Position> openedPositions = new List<Position>(); protected override void OnStart() { Positions.Closed += OnPositionClosed; } private void OnPositionClosed(PositionClosedEventArgs obj) { if (openedPositions.Contains(obj.Position)) { openedPositions.Remove(obj.Position); } } protected override void OnTick() { if (true) { TradeResult result = ExecuteMarketOrder(TradeType.Sell, Symbol, 1000); if (result.IsSuccessful) { openedPositions.Add(result.Position); } } bool allPositionsClosed = openedPositions.Count() == 0 ? true : false; } } }
@whis.gg
whis.gg
15 Dec 2016, 18:26
RE:
andi21 said:
No, the optimization starts to load the data from exact same time as you set the optimization.
You can contact me via email, pass the code and I will help you out with it.
@whis.gg