sascha.dawe
sascha.dawe's avatar

Info

Username:sascha.dawe
Name:sascha.dawe
Member since: 11 Feb 2019
Country:Australia

Favorite symbols:

AUDUSD

About

trader, programmer, contact at sascha.coding@gmail.com

Signature

None

Last Algorithm Comments

@Gerbil M5 Scalper:  11 Feb 2019, 02:36


Hi Zaknafein, Great work on this cbot. I have made a slight modification, so that when counting max positions, it only counts the open Gerbil positions. This allows you to open manual trades or run other cbots on the same account concurrently, if the max positions are set to one. I would like to work on this with you further. If you are interested, please contact me via my email account. using System; using System.Linq; using cAlgo.API; using cAlgo.API.Indicators; using cAlgo.API.Internals; using cAlgo.Indicators; namespace cAlgo.Robots {     [Robot(TimeZone = TimeZones.GMTStandardTime, AccessRights = AccessRights.None)]     public class Gerbil : Robot     {         [Parameter("Trade Start Hour", DefaultValue = 23, MinValue = 0, Step = 1)]         public int TradeStart { get; set; }         [Parameter("Trade End Hour", DefaultValue = 1, MinValue = 0, Step = 1)]         public int TradeEnd { get; set; }         [Parameter("Take Profit (Pips)", DefaultValue = 6, MinValue = 1, Step = 1)]         public int TakeProfit { get; set; }         [Parameter("Stop Loss (Pips)", DefaultValue = 150, MinValue = 1, Step = 1)]         public int StopLoss { get; set; }         [Parameter("Calculate Volume by Percentage?", DefaultValue = false)]         public bool RiskPercent { get; set; }         [Parameter("Quantity (%Risk or Lots)", DefaultValue = 0.01, MinValue = 0.01, Step = 0.01)]         public double Quantity { get; set; }         [Parameter("RSI Source")]         public DataSeries RSISource { get; set; }         [Parameter("RSI Period", DefaultValue = 7, MinValue = 1, Step = 1)]         public int RSIPeriods { get; set; }         [Parameter("RSI Overbought Level", DefaultValue = 80, MinValue = 1, Step = 1)]         public int RSIOverB { get; set; }         [Parameter("RSI Oversold Level", DefaultValue = 40, MinValue = 1, Step = 1)]         public int RSIOverS { get; set; }         [Parameter("ATR Periods", DefaultValue = 15, MinValue = 1, Step = 1)]         public int ATRPeriods { get; set; }         [Parameter("ATR From", DefaultValue = 10, MinValue = 1, Step = 1)]         public int ATRFrom { get; set; }         [Parameter("ATR To", DefaultValue = 100, MinValue = 1, Step = 1)]         public int ATRTo { get; set; }         [Parameter("Max Positions", DefaultValue = 1, MinValue = 1, Step = 1)]         public int MaxPos { get; set; }         [Parameter("Max DD Positions", DefaultValue = 0, MinValue = 0, Step = 1)]         public int MaxDDPos { get; set; }         [Parameter("KillHours", DefaultValue = 0, MinValue = 0, Step = 1)]         public int KillHours { get; set; }         private RelativeStrengthIndex rsi;         private AverageTrueRange atr;         private int DDPos = 0;         protected override void OnStart()         {             rsi = Indicators.RelativeStrengthIndex(RSISource, RSIPeriods);             atr = Indicators.AverageTrueRange(ATRPeriods, MovingAverageType.Simple);         }         protected override void OnBar()         {             if (Time.Hour >= TradeStart || Time.Hour < TradeEnd)             {                 var atrVal = atr.Result.LastValue * 100000;                 if (atrVal > ATRFrom && atrVal < ATRTo)                 {                     var positionsGerbil = Positions.FindAll("Gerbil", Symbol);                     if (positionsGerbil.Length < MaxPos)                     {                         if (rsi.Result.LastValue < RSIOverS)                         {                             Open(TradeType.Buy);                         }                         else if (rsi.Result.LastValue > RSIOverB)                         {                             Open(TradeType.Sell);                         }                     }                 }             }             if (KillHours != 0)             {                 foreach (var position in Positions.FindAll("Gerbil", Symbol))                 {                     if (Time > position.EntryTime.AddMinutes(KillHours * 60))                         ClosePosition(position);                 }             }         }         private void Open(TradeType tradeType)         {             //var position = Positions.Find("SampleRSI", Symbol, tradeType);             var volumeInUnits = CalculateVolume();             ExecuteMarketOrder(tradeType, Symbol, volumeInUnits, "Gerbil", StopLoss, TakeProfit);         }         double CalculateVolume()         {             if (!RiskPercent)             {                 return (Symbol.QuantityToVolumeInUnits(Quantity));             }             else             {                 // Calculate the total risk allowed per trade.                 double riskPerTrade = (Account.Balance * Quantity) / 100;                 double totalSLPipValue = (StopLoss + Symbol.Spread) * Symbol.PipValue;                 double calculatedVolume = riskPerTrade / totalSLPipValue;                 double normalizedCalculatedVolume = Symbol.NormalizeVolumeInUnits(calculatedVolume, RoundingMode.ToNearest);                 return normalizedCalculatedVolume;             }         }     } }

Last Forum Posts

@Auto Complete Bug Ctrader Editor:  17 May 2021, 10:48


Thanks Panagiotis,

If this helps, here is the error exception code that pops up.

Regards,

Sascha

@Auto Complete Bug Ctrader Editor:  12 May 2021, 05:18


Hi,

I have noticed a recurring bug in cTrader code editor in version 4 and it is quite annoying.

After using for some time, the code auto complete function stops working properly. I.e. it does not auto complete the method/variable when typing.

Furthermore, the application then crashes not long after this. These two issues seem to be related.

Regards,

Sascha

@Sound notifications not working in indicator:  22 Apr 2021, 13:06


Thanks Firemyst,

This appears to be the issue. I added a time delay of 10 seconds and the sound played fine. So it appears, that while loading the bars on start up, caused interference with the sound notification on the indicator.

Cheers,

Sascha

firemyst said:

sascha.dawe said:

Hi,

I am having trouble playing sound notifications in an indicator in the latest version of Ctrader 4.0.

Yes, I have sound enabled and notifications on Ctrader and Filesystem access is enabled. I have

also converted this code to a cBot and the sound works fine. What could be causing this issue?

See demonstration code below.

using System;
using System.IO;
using cAlgo.API;
using cAlgo.API.Internals;
using cAlgo.API.Indicators;
using cAlgo.Indicators;

namespace cAlgo
{
    [Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.FileSystem)]
    public class TestSound : Indicator
    {
        [Parameter("Enable Sound Alerts", Group = "Sound", DefaultValue = false)]
        public bool soundAlerts { get; set; }
        [Parameter("Sound Filename", Group = "Sound", DefaultValue = "foghorn.mp3")]
        public string filename { get; set; }

        private string path;
        private bool notified = false;

        protected override void Initialize()
        {
            try
            {
                var desktopFolder = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
                path = Path.Combine(desktopFolder, filename);
                Print(path);
            } catch (Exception error)
            {
                Print("Error: " + error);
            }
            PlaySound();
        }

        public override void Calculate(int index)
        {
            if (!notified)
            {
                notified = true;
                PlaySound();
            }
        }

        private void PlaySound()
        {
            if (soundAlerts)
            {
                try
                {
                    Notifications.PlaySound(path);
                } catch (Exception error)
                {
                    Print("Error: " + error);
                }
            }
        }
    }
}

Have you tried stepping through your code in Visual Studio debug mode to see what happens?

Also, because ticks could be coming in rather quickly, the system might be trying to play, but then gets stopped immediately when the next tick comes in because the "notified" variable is never set to true. I've had that happen before when trying to play sounds too quickly in succession.

Finally, what's the Print/logging output?

@Sound notifications not working in indicator:  19 Apr 2021, 03:55


Hi,

I am having trouble playing sound notifications in an indicator in the latest version of Ctrader 4.0.

Yes, I have sound enabled and notifications on Ctrader and Filesystem access is enabled. I have

also converted this code to a cBot and the sound works fine. What could be causing this issue?

See demonstration code below.

using System;
using System.IO;
using cAlgo.API;
using cAlgo.API.Internals;
using cAlgo.API.Indicators;
using cAlgo.Indicators;

namespace cAlgo
{
    [Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.FileSystem)]
    public class TestSound : Indicator
    {
        [Parameter("Enable Sound Alerts", Group = "Sound", DefaultValue = false)]
        public bool soundAlerts { get; set; }
        [Parameter("Sound Filename", Group = "Sound", DefaultValue = "foghorn.mp3")]
        public string filename { get; set; }

        private string path;
        private bool notified = false;

        protected override void Initialize()
        {
            try
            {
                var desktopFolder = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
                path = Path.Combine(desktopFolder, filename);
                Print(path);
            } catch (Exception error)
            {
                Print("Error: " + error);
            }
            PlaySound();
        }

        public override void Calculate(int index)
        {
            if (!notified)
            {
                notified = true;
                PlaySound();
            }
        }

        private void PlaySound()
        {
            if (soundAlerts)
            {
                try
                {
                    Notifications.PlaySound(path);
                } catch (Exception error)
                {
                    Print("Error: " + error);
                }
            }
        }
    }
}

@Martingale, ading position direction:  11 Dec 2020, 07:10


enisjahja said:

Hi, 

Can anybody help me with this code:

(I want to make when it hits SL enter opposite direction and when it hits TP countinue with the position trade direction.)

This is the martingale code:

// -------------------------------------------------------------------------------------------------
//
//    This code is a cTrader Automate API example.
//
//    This cBot is intended to be used as a sample and does not guarantee any particular outcome or
//    profit of any kind. Use it at your own risk.
//    
//    All changes to this file might be lost on the next application update.
//    If you are going to modify this file please make a copy using the "Duplicate" command.
//
//    The "Sample Martingale cBot" creates a random Sell or Buy order. If the Stop loss is hit, a new 
//    order of the same type (Buy / Sell) is created with double the Initial Volume amount. The cBot will 
//    continue to double the volume amount for  all orders created until one of them hits the take Profit. 
//    After a Take Profit is hit, a new random Buy or Sell order is created with the Initial Volume amount.
//
// -------------------------------------------------------------------------------------------------

using System;
using System.Linq;
using cAlgo.API;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
using cAlgo.Indicators;

namespace cAlgo
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class SampleMartingalecBot : Robot
    {
        [Parameter("Initial Quantity (Lots)", Group = "Volume", DefaultValue = 1, MinValue = 0.01, Step = 0.01)]
        public double InitialQuantity { get; set; }

        [Parameter("Stop Loss", Group = "Protection", DefaultValue = 40)]
        public int StopLoss { get; set; }

        [Parameter("Take Profit", Group = "Protection", DefaultValue = 40)]
        public int TakeProfit { get; set; }


        private Random random = new Random();

        protected override void OnStart()
        {
            Positions.Closed += OnPositionsClosed;

            ExecuteOrder(InitialQuantity, GetRandomTradeType());
        }

        private void ExecuteOrder(double quantity, GetRandomTradeType())
        {
            var volumeInUnits = Symbol.QuantityToVolumeInUnits(quantity);
            var result = ExecuteMarketOrder(tradeType, SymbolName, volumeInUnits, "Martingale", StopLoss, TakeProfit);

            if (result.Error == ErrorCode.NoMoney)
                Stop();
        }

        private void OnPositionsClosed(PositionClosedEventArgs args)
        {
            Print("Closed");
            var position = args.Position;

            if (position.Label != "Martingale" || position.SymbolName != SymbolName)
                return;

            if (position.GrossProfit > 0)
            {
                ExecuteOrder(InitialQuantity, position.TradeType);
            }
            else
            {
                ExecuteOrder(position.Quantity * 2, position.TradeType==TradeType.Buy?TradeType.Sell:TradeType.Buy);
            }
        }

        private TradeType GetRandomTradeType()
        {
            return random.Next(2) == 0 ? TradeType.Buy : TradeType.Sell;
        }
    }
}

Try this code: I have update the OnPositionsClosed() function.

Regards,

Sascha

@Loading historical tick data:  27 Jul 2020, 17:13


Hi, 

The below sample shows loading historical bars. 

Is it possible to show a code sample loading historical tick data on an indicator?

Thanks,

Sascha

Note, in the previous versions tick data was accessible only if cBot or indicator was running on Tick1 chart and only for bid prices using old MarketSeries. With the new API you can access tick data from any timeframe and use bid and ask prices

Load more history

For both Bars and Ticks you can load more history using LoadMoreHistory or LoadMoreHistoryAsync methods.
Below Is an example of loading 10 000 bars on the chart

Print("{0} bar on the chart. Loading 10 000 bars", Bars.Count);
while (Bars.Count < 10000)
{
    var loadedCount = Bars.LoadMoreHistory();
    Print("Loaded {0} bars", loadedCount);
    if (loadedCount == 0)
        break;
}
Print("Finished, total bars {0}", Bars.Count);

Output:
1143 bar on the chart. Loading 10 000 bars
Loaded 1141 bars
Loaded 1162 bars
Loaded 1129 bars
Loaded 1090 bars
Loaded 1126 bars
Loaded 1134 bars
Loaded 1134 bars
Loaded 1166 bars
Finished, total bars 10225

@Trouble passing indicator value to another indicator.:  18 May 2020, 14:17


PanagiotisCharalampous said:

Hi sascha.dawe,

There seem to be a lot of issues with your code. A couple of points you should revisit

1) Try adding output attributes to your SampleSignalMultiSymbol indicator

2) Revisit your indexing. Doesn't seem to make much sense to me.

Best Regards,

Panagiotis 

Join us on Telegram

Thanks Panagiotis,

Is an output attribute strictly necessary though for the signal to be passed through?

I don't really want an output to the screen from this indicator. I just want various time frame signals to be passed through

to the one chart panel, where buy/sell buttons will be displayed on screen.

Regards,

Sascha

@Trouble passing indicator value to another indicator.:  17 May 2020, 09:19


Hi,

I am not sure what I am doing wrong here. I am trying to pass a value from a multi symbol indicator to another indication. This will be a panel eventually, with the ability to

see different trade signals coming through on the one chart.

The primary indicator is working as it should.

But the sample panel indicator is returning NaN values.

using System;
using cAlgo.API;
using cAlgo.API.Internals;
using cAlgo.API.Indicators;
using cAlgo.Indicators;

namespace cAlgo
{
    [Indicator(IsOverlay = false, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class SampleSignalMultiSymbol : Indicator
    {
        [Parameter("SMA Short Period ", DefaultValue = 5)]
        public int shortPeriod { get; set; }

        [Parameter("SMA Long Period ", DefaultValue = 210)]
        public int longPeriod { get; set; }
        [Parameter("Symbol 1", DefaultValue = CurrencyPairs.AUDUSD)]
        public CurrencyPairs currencyPair1 { get; set; }
        [Parameter("Time Frame ", DefaultValue = "Daily")]
        public TimeFrame timeframe { get; set; }

        public IndicatorDataSeries SMA1;
        public IndicatorDataSeries SMA2;
        public IndicatorDataSeries signal;

        public SimpleMovingAverage sma5, sma210;

        private MarketSeries customSeries;
        private Symbol symbol1;
        private int lastIndex;

        public enum CurrencyPairs
        {
            EMPTY,
            AUDUSD,
            EURUSD,
            GBPUSD,
            USDJPY,
            USDCHF,
            USDCAD,
            AUDCAD,
            AUDCHF,
            AUDNZD,
            AUDSGD,
            EURAUD,
            EURCHF,
            EURGBP,
            GBPAUD,
            GBPCHF,
            NZDUSD,
            EURJPY,
            GBPJPY,
            AUDJPY,
            CHFJPY,
            CADJPY,
            EURCAD,
            GBPCAD,
            NZDJPY,
            GBPNZD,
            EURNZD,
            CADCHF,
            NZDCAD,
            NZDCHF,
            SGDJPY,
            AUS200,
            US30,
            US500,
            US2000,
            XPTUSD,
            XAUUSD,
            XTIUSD,
            UK100,
            JPN225
        }

        protected override void Initialize()
        {
            //Symbol 1
            if (currencyPair1.ToString() != "EMPTY" && MarketData.GetSymbol(currencyPair1.ToString()) != null)
            {
                signal = CreateDataSeries();
                SMA1 = CreateDataSeries();
                SMA2 = CreateDataSeries();
                symbol1 = MarketData.GetSymbol(currencyPair1.ToString());
                customSeries = MarketData.GetSeries(symbol1, timeframe);
                sma5 = Indicators.SimpleMovingAverage(customSeries.Close, shortPeriod);
                sma210 = Indicators.SimpleMovingAverage(customSeries.Close, longPeriod);

            }
        }

        public override void Calculate(int index)
        {
            var indexUserSelectedTimeFrame = GetIndexByDate(customSeries, MarketSeries.OpenTime[index]);
            if (indexUserSelectedTimeFrame != -1)
            {
                double close = Bars.ClosePrices[indexUserSelectedTimeFrame - 1];
                double previousClose = Bars.ClosePrices[index - 2];
                SMA1[index] = sma5.Result[indexUserSelectedTimeFrame];
                SMA2[index] = sma210.Result[indexUserSelectedTimeFrame];
                if (close > SMA1[indexUserSelectedTimeFrame - 1] && previousClose < SMA1[indexUserSelectedTimeFrame - 2])
                {
                    signal[index] = 1;
                }
                else if (close < SMA1[indexUserSelectedTimeFrame - 1] && previousClose > SMA1[indexUserSelectedTimeFrame - 2])
                {
                    signal[index] = -1;
                }
                else
                {
                    signal[index] = 0;
                }
                if (index != lastIndex)
                {
                    lastIndex = index;
                    Print(signal[index]);
                }
            }
        }

        private int GetIndexByDate(MarketSeries series, DateTime time)
        {
            for (int i = series.Close.Count - 1; i > 0; i--)
            {
                if (time == series.OpenTime[i])
                {
                    return i;
                }
                else if (series.OpenTime[i] < time)
                {
                    return i;
                }
            }
            return -1;
        }

    }
}

This next code snippet is the panel that the first signal gets sent to.

using System;
using cAlgo.API;
using cAlgo.API.Internals;
using cAlgo.API.Indicators;
using cAlgo.Indicators;

namespace cAlgo
{
    [Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class SamplePanel : Indicator
    {
        [Parameter("SMA Short Period ", DefaultValue = 5)]
        public int shortPeriod { get; set; }

        [Parameter("SMA Long Period ", DefaultValue = 210)]
        public int longPeriod { get; set; }
        [Parameter("Symbol 1", DefaultValue = CurrencyPairs.AUDUSD)]
        public CurrencyPairs currencyPair1 { get; set; }
        [Parameter("Time Frame ", DefaultValue = "Daily")]
        public TimeFrame timeframe { get; set; }

        public SampleSignalMultiSymbol multiSymbol;
        public IndicatorDataSeries signal;
        private Symbol symbol1;
        private MarketSeries customSeries;

        public enum CurrencyPairs
        {
            EMPTY,
            AUDUSD,
            EURUSD,
            GBPUSD,
            USDJPY,
            USDCHF,
            USDCAD,
            AUDCAD,
            AUDCHF,
            AUDNZD,
            AUDSGD,
            EURAUD,
            EURCHF,
            EURGBP,
            GBPAUD,
            GBPCHF,
            NZDUSD,
            EURJPY,
            GBPJPY,
            AUDJPY,
            CHFJPY,
            CADJPY,
            EURCAD,
            GBPCAD,
            NZDJPY,
            GBPNZD,
            EURNZD,
            CADCHF,
            NZDCAD,
            NZDCHF,
            SGDJPY,
            AUS200,
            US30,
            US500,
            US2000,
            XPTUSD,
            XAUUSD,
            XTIUSD,
            UK100,
            JPN225
        }

        protected override void Initialize()
        {
            //Symbol 1
            if (currencyPair1.ToString() != "EMPTY" && MarketData.GetSymbol(currencyPair1.ToString()) != null)
            {
                signal = CreateDataSeries();
                symbol1 = MarketData.GetSymbol(currencyPair1.ToString());
                customSeries = MarketData.GetSeries(symbol1, TimeFrame.Minute5);
                multiSymbol = Indicators.GetIndicator<SampleSignalMultiSymbol>(shortPeriod, longPeriod, currencyPair1, TimeFrame.Minute5);
            }
        }

        public override void Calculate(int index)
        {
            //Symbo1 1
            if (currencyPair1.ToString() != "EMPTY" && MarketData.GetSymbol(currencyPair1.ToString()) != null)
            {
                var indexUserSelectedTimeFrame = GetIndexByDate(customSeries, MarketSeries.OpenTime[index]);
                if (indexUserSelectedTimeFrame != -1)
                {
                    signal[index] = multiSymbol.signal[indexUserSelectedTimeFrame];
                    Print(signal[index]);
                }
            }
        }

        private int GetIndexByDate(MarketSeries series, DateTime time)
        {
            for (int i = series.Close.Count - 1; i > 0; i--)
            {
                if (time == series.OpenTime[i])
                {
                    return i;
                }
                else if (series.OpenTime[i] < time)
                {
                    return i;
                }
            }
            return -1;
        }

    }
}

@Is it possible to move panels on screen with mouse:  23 Mar 2020, 11:59


Fantastic,

This is a good starting point.

Thanks,

Sascha

@Is it possible to move panels on screen with mouse:  21 Mar 2020, 01:34


Hi, 

Is there a method to move custom UI elements (introduced in 3.6) around the chart with a mouse? Such as the quick trading panel, for example. I feel this would be more natural for the user, rather than specifying vertical and horizontal alignment.

Also, is there a way to get more control on placement, rather than vertical alignment top horizontal alignment right. Can we specify x and y coordinates instead?

Thanks,

Sascha

Notification Publishing copyrighted material is strictly prohibited. If you believe there is copyrighted material in this section you may use the Copyright Infringement Notification form to submit a claim.

No uploaded.

Warning! Executing cBots downloaded from this section may result in loss of funds. Use them at your own risk.

No uploaded.