Topics
Forum Topics not found
Replies
amusleh
22 Dec 2021, 09:28
Hi,
Please read API references and check the examples there before asking a question: cAlgo API Reference - ChartHorizontalLine Interface (ctrader.com)
Try this:
using System;
using System.Linq;
using cAlgo.API;
namespace cAlgo
{
[Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class AWCPDaily : Robot
{
private TextBlock tb = new TextBlock();
private ChartHorizontalLine sll;
[Parameter("Take Profit", DefaultValue = 100)]
public double tp { get; set; }
[Parameter("Stop Profit", DefaultValue = 90)]
public double sl { get; set; }
[Parameter("FontSize", DefaultValue = 16, Group = "Text")]
public int FontSize { get; set; }
[Parameter("Space to Corner", DefaultValue = 10, Group = "Text")]
public int Margin { get; set; }
[Parameter("Horizental Alignment", DefaultValue = HorizontalAlignment.Left, Group = "Text")]
public HorizontalAlignment HAlignment { get; set; }
[Parameter("Vertical Alignment", DefaultValue = VerticalAlignment.Top, Group = "Text")]
public VerticalAlignment VAlignment { get; set; }
[Parameter("Color", DefaultValue = "Red", Group = "Text")]
public string Color1 { get; set; }
[Parameter("Opacity", DefaultValue = 0.7, MinValue = 0.1, MaxValue = 1, Group = "Text")]
public double Opacity { get; set; }
[Parameter("Text Alignment", DefaultValue = TextAlignment.Center, Group = "Text")]
public TextAlignment Alignment { get; set; }
protected override void OnStart()
{
var y = Chart.BottomY + ((Chart.TopY - Chart.BottomY) / 2);
sll = Chart.DrawHorizontalLine("horizontal", y, Color.Red);
sll.IsInteractive = true;
Chart.AddControl(tb);
tb.Text = "sl : " + sl.ToString() + ", " + "tp : " + tp.ToString() + "\n EQ: " + Account.Equity + ", ML%: " + Account.MarginLevel + "\nVP: " + Account.Margin / Account.Balance + "V: " + sll.Y;
tb.FontSize = FontSize;
tb.ForegroundColor = Color1.TrimEnd();
tb.HorizontalAlignment = HAlignment;
tb.VerticalAlignment = VAlignment;
tb.TextAlignment = Alignment;
tb.Margin = Margin;
tb.Opacity = Opacity;
}
protected override void OnTick()
{
foreach (var position in Positions)
{
if (Account.Equity > tp || Account.Equity < sl)
{
ClosePositionAsync(position);
}
}
foreach (var order in PendingOrders)
{
if (Account.Equity > tp || Account.Equity < sl)
{
CancelPendingOrder(order);
}
}
}
}
}
You have to set a chart object IsInteractive property to true, then you will be able to change it on the chart.
@amusleh
amusleh
22 Dec 2021, 09:24
Hi,
Try this:
using cAlgo.API;
using cAlgo.API.Indicators;
namespace cAlgo.Robots
{
[Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class NewcBot : Robot
{
private BollingerBands _bbands;
protected override void OnStart()
{
_bbands = Indicators.BollingerBands(Bars.ClosePrices, 20, 2, MovingAverageType.Simple);
}
protected override void OnBar()
{
// When a bar crossed upper band from below
if (Bars.Last(2).High < _bbands.Top.Last(2) && Bars.Last(1).High > _bbands.Top.Last(1))
{
}
// When a bar crossed upper band from above
if (Bars.Last(2).Low > _bbands.Top.Last(2) && Bars.Last(1).Low < _bbands.Top.Last(1))
{
}
}
}
}
@amusleh
amusleh
22 Dec 2021, 09:20
Hi,
The deal map is for trades, not for positions.
But if you want to have something like deal map for positions you can try this:
using cAlgo.API;
using System;
namespace cAlgo.Robots
{
[Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class NewcBot : Robot
{
protected override void OnStart()
{
UpdateDealMaps();
Positions.Opened += Positions_Opened;
Positions.Closed += Positions_Closed;
}
protected override void OnTick()
{
UpdateDealMaps();
}
private void Positions_Opened(PositionOpenedEventArgs obj)
{
if (obj.Position.SymbolName.Equals(SymbolName, StringComparison.OrdinalIgnoreCase) == false) return;
DrawDealpMap(obj.Position);
}
private void Positions_Closed(PositionClosedEventArgs obj)
{
if (obj.Position.SymbolName.Equals(SymbolName, StringComparison.OrdinalIgnoreCase) == false) return;
// Remove the position deal map when it got closed
Chart.RemoveObject(obj.Position.Id.ToString());
}
private void UpdateDealMaps()
{
foreach (var position in Positions)
{
if (position.SymbolName.Equals(SymbolName, StringComparison.OrdinalIgnoreCase) == false) continue;
DrawDealpMap(position);
}
}
private void DrawDealpMap(Position position)
{
var color = position.TradeType == TradeType.Buy ? Color.Green : Color.Red;
Chart.DrawTrendLine(position.Id.ToString(), position.EntryTime, position.EntryPrice, Server.Time, Symbol.Bid, color);
}
}
}
It draws a deal map line when a position is opened and it keeps changing it based on price change until the position got closed, after that it removes the line.
@amusleh
amusleh
22 Dec 2021, 09:12
RE: RE:
mohsabry.ms said:
Hi,
Did you mean that " if (Server.TimeInUtc.TimeOfDay.TotalMinutes == 1)"
or What?
Hi,
No, I mean if you know the time you want to pause your cBot then you can do it with code, ex:
using cAlgo.API;
using System;
using System.Linq;
using System.Globalization;
using System.Collections.Generic;
namespace cAlgo.Robots
{
[Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class NewcBot : Robot
{
private List<DayOfWeek> _pauseDays;
private TimeSpan _startTime, _endTime;
private bool _isPaused;
[Parameter("Days", DefaultValue = "Friday,Saturday", Group = "Pause")]
public string Days { get; set; }
[Parameter("Start Time", DefaultValue = "07:00:00", Group = "Pause")]
public string StartTime { get; set; }
[Parameter("End Time", DefaultValue = "16:00:00", Group = "Pause")]
public string EndTime { get; set; }
protected override void OnStart()
{
_pauseDays = Days.Split(',').Select(day => (DayOfWeek)Enum.Parse(typeof(DayOfWeek), day)).ToList();
if (TimeSpan.TryParse(StartTime, CultureInfo.InvariantCulture, out _startTime) == false)
{
Print("Invalid StartTime");
Stop();
}
if (TimeSpan.TryParse(EndTime, CultureInfo.InvariantCulture, out _endTime) == false)
{
Print("Invalid EndTime");
Stop();
}
Timer.Start(1);
}
protected override void OnTimer()
{
if (_pauseDays.Contains(Server.Time.DayOfWeek) && Server.Time.TimeOfDay >= _startTime && Server.Time.TimeOfDay <= _endTime)
{
_isPaused = true;
}
_isPaused = false;
}
protected override void OnBar()
{
if (_isPaused) return;
// Otherwise continue running cBot logic
}
protected override void OnTick()
{
if (_isPaused) return;
// Otherwise continue running cBot logic
}
}
}
The above cBot will be paused based on your provided start/end time and days of week.
@amusleh
amusleh
21 Dec 2021, 14:38
Hi,
You can use the reconcile request: https://spotware.github.io/open-api-docs/messages/#protooareconcilereq
For live real time update you should use execution event: https://spotware.github.io/open-api-docs/messages/#protooaexecutionevent
@amusleh
amusleh
21 Dec 2021, 14:37
Hi,
No, I don't have such a code example, please use the Alert library I posted on my previously.
Read its documentation: Home · afhacker/ctrader-alert_popup Wiki (github.com)
You can send Telegram messages just with one line of code if you use the alert library.
@amusleh
amusleh
21 Dec 2021, 09:44
Hi,
You can use Server.Time, set a time interval when you want to run your cBot and check if the current time is inside your specified time interval or not, if its not then skip the OnBar/OnTick methods otherwise continue running them.
You don't have to start/stop your cBot, you can do it with code.
@amusleh
amusleh
21 Dec 2021, 09:40
Hi,
Try this:
using cAlgo.API;
using System;
using System.Linq;
namespace cAlgo.Robots
{
[Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class NewcBot : Robot
{
protected override void OnStart()
{
foreach (var trade in History)
{
if (trade.SymbolName.Equals(SymbolName, StringComparison.OrdinalIgnoreCase) == false) continue;
DrawDealpMap(trade);
}
Positions.Closed += Positions_Closed;
}
private void Positions_Closed(PositionClosedEventArgs obj)
{
if (obj.Position.SymbolName.Equals(SymbolName, StringComparison.OrdinalIgnoreCase) == false) return;
var trade = History.FirstOrDefault(iTrade => iTrade.PositionId == obj.Position.Id);
if (trade != null)
{
DrawDealpMap(trade);
}
}
private void DrawDealpMap(HistoricalTrade trade)
{
var color = trade.TradeType == TradeType.Buy ? Color.Green : Color.Red;
Chart.DrawTrendLine(trade.PositionId.ToString(), trade.EntryTime, trade.EntryPrice, trade.ClosingTime, trade.ClosingPrice, color);
}
}
}
@amusleh
amusleh
20 Dec 2021, 13:15
Hi,
You can post a job request or ask one of our consultants to do it for you.
@amusleh
amusleh
20 Dec 2021, 10:08
Hi,
Please read the library Wiki, there you will find a sample: Proper Implementation · afhacker/ctrader-alert_popup Wiki (github.com)
@amusleh
amusleh
20 Dec 2021, 09:55
Hi,
I'm not sure what you are after?
Do you want to access tick time frames data? if that's what you want to do then you can use the above posted code of mine or this complete version:
using cAlgo.API;
using cAlgo.API.Internals;
using System.Text;
namespace cAlgo.Robots
{
[Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class Toan012speedforumreplyL5tick : Robot
{
[Parameter("Tick TimeFrame", DefaultValue = "Tick200")]
public TimeFrame TickTimeFrame { get; set; }
private Bars _tickBars;
protected override void OnStart()
{
// Change the time frame if you want to use other tick time frames
// Or get the time frame via a cBot parameter
_tickBars = MarketData.GetBars(TimeFrame.Tick200);
// This will call the TickBars_Tick method every 200 ticks
_tickBars.Tick += TickBars_Tick;
}
private void TickBars_Tick(BarsTickEventArgs obj)
{
var stringBuilder = new StringBuilder();
stringBuilder.AppendFormat("New Tick bar received, Open: {0} | High: {1} | Low: {2} | Close: {3}", obj.Bars.LastBar.Open, obj.Bars.LastBar.High, obj.Bars.LastBar.Low, obj.Bars.LastBar.Close);
Chart.DrawStaticText("text", stringBuilder.ToString(), VerticalAlignment.Top, HorizontalAlignment.Right, Color.Red);
}
}
}
If you are looking to execute something on each new tick, then use your cBot OnTick method or symbol Tick event in case of multiple symbols.
@amusleh
amusleh
20 Dec 2021, 09:49
RE: RE:
m4trader4 said:
Ahmad
Sure will do that.
I am trying to get the guppys ema's check using parallel/concurency using concurrent collections, appreciate if you could have a look at the code provide pointers for faster calculations.
public string GuppyCheck(int bI, int Period, double CandleHigh, double CandleLow) { string RetGuppyCheck = "False"; var GuppyResult = Indicators.ExponentialMovingAverage(Bars.ClosePrices, Period).Result.Last(Bars.Count - bI - 1); if ((GuppyResult <= CandleHigh && GuppyResult >= CandleLow)) { RetGuppyCheck = "True"; } else RetGuppyCheck = "False"; return RetGuppyCheck; } public string ChartRG(int bI, double CandleHigh, double CandleLow) { // Print("BarIndex=" + bI + "=BarCount=" + Bars.Count); string ChartRGResult = "nEVT"; var TempShortList = new List<string>(); var TempLongList = new List<string>(); TempShortList.Add(GuppyCheck(bI, 3, CandleHigh, CandleLow)); TempShortList.Add(GuppyCheck(bI, 5, CandleHigh, CandleLow)); TempShortList.Add(GuppyCheck(bI, 8, CandleHigh, CandleLow)); TempShortList.Add(GuppyCheck(bI, 10, CandleHigh, CandleLow)); TempShortList.Add(GuppyCheck(bI, 12, CandleHigh, CandleLow)); TempShortList.Add(GuppyCheck(bI, 15, CandleHigh, CandleLow)); TempLongList.Add(GuppyCheck(bI, 30, CandleHigh, CandleLow)); TempLongList.Add(GuppyCheck(bI, 35, CandleHigh, CandleLow)); TempLongList.Add(GuppyCheck(bI, 40, CandleHigh, CandleLow)); TempLongList.Add(GuppyCheck(bI, 45, CandleHigh, CandleLow)); TempLongList.Add(GuppyCheck(bI, 50, CandleHigh, CandleLow)); TempLongList.Add(GuppyCheck(bI, 60, CandleHigh, CandleLow)); var CountTempShortTrue = TempShortList.Count(item => item.Contains("True")); var CountTempLongTrue = TempLongList.Count(item => item.Contains("True")); //Print("CountTempShortTrue=" + CountTempShortTrue + "CountTempLongTrue" + CountTempLongTrue); if (CountTempShortTrue == 6) { // Print("All 6 In"); ChartRGResult = "EVT"; } if (CountTempShortTrue == 6 && CountTempLongTrue == 6) { // Print("All B6 In R6 In"); ChartRGResult = "EVT"; } if (CountTempShortTrue == 6 && CountTempLongTrue >= 1 && CountTempLongTrue < 6) { //Print("All B6 In R6 In"); ChartRGResult = "nEVT"; } return ChartRGResult; }
Hi,
I don't see any concurrent collection or code on your posted code.
Some things you can use concurrency easily without any side effect will be Linq queries and deterministic methods or loops witch will not make any change on your app state.
For Linq queries you can use Parallel Linq and for loops you can use Parallet.For or Parallel.Foreach.
Concurrency is hard, if you want to use it you must have a good knowledge of it.
If the amount of data is not large or your functions that you want to run on each item of your data is not getting lots of time then using concurrency will have negative impact on your code performance.
If you are interested in this topic I recommend you to read this book: Concurrency in .NET: Modern patterns of concurrent and parallel programming: Terrell, Riccardo: 9781617292996: Amazon.com: Books
And as I said on my previous post, after cTrader 4.2 you will be able to use Tasks and async/await, which will allow you to run your code asynchronously, its not same thing as concurrency but it will help a lot in terms of performance and resource usage.
I have worked on lots of cTrader indicators and cBots, and I have never faced any need for using concurrency, before using it please ask yourself if you really need it or not?
And benchmark your code sequential version alongside concurrent version, be sure it gives you benefit and it doesn't have any negative impact on performance.
@amusleh
amusleh
20 Dec 2021, 09:38
Hi,
Not sure what those functions return, but I tried my best:
private int SellStopPoint()
{
double sto = Bars.HighPrices.Maximum(7) + 1.5 * Symbol.Spread;
int poi = Convert.ToInt32((sto - Bid) * Math.Pow(10, Symbol.Digits));
return (poi);
}
private int BuyStopPoint()
{
double sto = Bars.LowPrices.Minimum(7) + 1.5 * Symbol.Spread;
int poi = Convert.ToInt32((Ask - sto) * Math.Pow(10, Symbol.Digits));
return (poi);
}
If there something wrong please correct it based on cTrader automate API:
@amusleh
amusleh
20 Dec 2021, 09:31
Hi,
You can use Telegram API on your indicators/cBots, you can implement the API in .NET by your self or I recommend you to use the popular Telegram.Bot library: TelegramBots/Telegram.Bot: .NET Client for Telegram Bot API (github.com)
If you are looking for an example or a quick way you can use this library: afhacker/ctrader-alert_popup: Alert Popup For cTrader (github.com)
@amusleh
amusleh
17 Dec 2021, 09:28
Hi,
Concurrency and multi threading is your responsibility, APIs mostly aren't thread safe.
If you want to use multi threading you must do all the work.
After cTrader 4.2 release you will be able to use .NET async/await and Tasks, so you don't have to use Parallel or create new threads by your self.
Please read the documentation of Task, Parallel, and .NET multi threading before using them.
@amusleh
amusleh
17 Dec 2021, 09:24
RE: RE:
agung.ghani said:
amusleh said:
Hi,
Did you set your indicator access right to FullAccess? Its None, change it to FullAccess.
Great. It's working. Many thanks for your help.
However, I just realized that the pop up alert is repeated 4 times every time the indicator is triggered. I didn't see any loop condition in the code. What is the possible reason that pop up alert is triggered four times?
Best regards
Hi,
You have to call the ShowPopup only once per bar, and only for new bars not for historical bars.
The popup will be shows as many times you call the ShowPopup method.
@amusleh
amusleh
23 Dec 2021, 09:08
Hi,
What do you mean by: "i dont' know how to add signal line cross histogram to it?"
Can you show this on a chart screenshot?
Not sure about the exact size of library but if you use the newer version library the size might reduce.
You don't need that library to show a popup alert or play a sound alert.
cTrader automate API has the email and sound alert itself under Notifications: cAlgo API Reference - INotifications Interface (ctrader.com)
@amusleh