Replies

david.sanchez
28 Feb 2020, 10:45

RE:

Panagiotis,

Thank you for your advice.

I will give it a second try, maybe you are right and they are now capable of doing it.

Sincerely,

David 


@david.sanchez

david.sanchez
28 Feb 2020, 10:15

Hi Panagiotis,

So it seems to solve that particular issue, now there were no error messages and I was able to compile the code.

However, When I tried to run the cbot on EURUSD ( I added EURUSD to the code through the "+" sign beow the code in ctrader) it stopped itself after a few seconds.

So I assume there is something in the code which is not properly used.

I suspect either these lines: 

var ticks = MarketData.GetTicks("AUDUSD");

Are the brackets supposed to be left out empty? I could not find the correct API reference to check it myself...

-If yes how can I get Bid/ Ask data as Series for particular pairs like AUDUSD and EURUSD?

Or these lines might cause it to stop:

var Spread = CreateDataSeries();

            for (int X = 0; X < 10; X++)
            {

                Spread[X] = series[X] - series2[X];

            }

"series" is supposed to be the Ask dataseries of AUDUSD and "series2" Bid of EURUSD

since I want to use the difference of both series in the bollinger bands, I did it that way.

or maybe it is somewhere else here is the entire code:

using System;
using System.Linq;
using System.Collections.Generic;
using cAlgo.API;
using cAlgo.API.Requests;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
using cAlgo.Indicators;

namespace cAlgo
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class Arbitrage1 : Robot
    {
       
      
        private BollingerBands bbds;

        protected override void OnStart()
        {
                       
            var ticks = MarketData.GetTicks("AUDUSD");
            var series = CreateDataSeries();
            int i = 0;
            foreach (var tick in ticks)
            {
                series[i] = tick.Ask;
                i++;
            }

            var ticks2 = MarketData.GetTicks("EURUSD");
            var series2 = CreateDataSeries();
            int t = 0;
            foreach (var tick in ticks)
            {
                series2[t] = tick.Bid;
                t++;
            }

            var Spread = CreateDataSeries();

            for (int X = 0; X < 10; X++)
            {

                Spread[X] = series[X] - series2[X];

            }

            var bbds = Indicators.BollingerBands(Spread, 10, 1, MovingAverageType.Simple);

        }
        protected override void OnTick()
        {
                        
            var ticks = MarketData.GetTicks("AUDUSD");
            var series = CreateDataSeries();
            int i = 0;
            foreach (var tick in ticks)
            {
                series[i] = tick.Ask;
                i++;
            }

            var ticks2 = MarketData.GetTicks("EURUSD");
            var series2 = CreateDataSeries();
            int t = 0;
            foreach (var tick in ticks)
            {
                series2[t] = tick.Bid;
                t++;
            }

            var Spread = CreateDataSeries();
           
            for (int X = 0; X < 10; X++)
            {
               
                Spread[X] = series[X] - series2[X];
               
            }
                       
                      
            if (bbds.Top[0] <= Spread[0]) 
            {
                ExecuteMarketOrder(TradeType.Sell,"AUDUSD",100000);
                ExecuteMarketOrder(TradeType.Buy,"EURUSD",100000);

                var openPositions1 = Positions.FindAll("Arbitrage1", "AUDUSD");

                foreach (var order in openPositions1)
                {
                    ClosePosition(order);
                }

                var openPositions2 = Positions.FindAll("Arbitrage1", "EURUSD");

                foreach (var order in openPositions2)
                {
                    ClosePosition(order);
                }

            }
            else if (bbds.Bottom[0] >= Spread[0])
            {
                ExecuteMarketOrder(TradeType.Buy,"AUDUSD",100000);
                ExecuteMarketOrder(TradeType.Sell,"EURUSD",100000);

                var openPositions1 = Positions.FindAll("Arbitrage1", "AUDUSD");

                foreach (var order in openPositions1)
                {
                    ClosePosition(order);
                }

                var openPositions2 = Positions.FindAll("Arbitrage1", "EURUSD");

                foreach (var order in openPositions2)
                {
                    ClosePosition(order);
                }

            }
                
        }
    }
}

I appreciate your support.

Sincerely,

David


@david.sanchez

david.sanchez
27 Feb 2020, 11:59

RE:

On a higher level we are all trying to do the same thing, make money :) - that's true ^^

With the following lines, I tried to get bid/ask data for those two pairs as a series, because Bollinger bands can only be used with series inputs.

Are they used correcly? Note that I typed in the actual pairs which were not in your sample..., so probably false?

           var ticks = MarketData.GetTicks("AUDUSD");
            var series = CreateDataSeries();
            int i = 0;
            foreach (var tick in ticks)
            {
                series[i] = tick.Ask;
                i++;
            }

            var ticks2 = MarketData.GetTicks("EURUSD");
            var series2 = CreateDataSeries();
            int t = 0;
            foreach (var tick in ticks)
            {
                series2[t] = tick.Bid;
                t++;
            }

With the next lines I tried to subtract both series so that I can use it in the Bollinger bands indicator

            var Spread = CreateDataSeries();
           
            for (int X = 0; X < 10; X++)
            {
               
                Spread[X] = series[X] - series2[X];
               
            }

On these lines I wanted to declare variables for the upper and lower bound of Bollinger bands calculated on the spread series, is this done correctly? 

            var bbds = Indicators.BollingerBands(Spread, 10, 1, MovingAverageType.Simple);//upper Bollinger band
            var bbds2 = Indicators.BollingerBands(Spread, 10, -1, MovingAverageType.Simple)//lower Bollinger band

At last here I want to test if the current value of the Spread series Spread[0] is overpriced, equal or more than upper bollinger band.

What are you trying to compare?

"bbds" is supposed to be the upper bollinger band calculated on the spread series and Spread[0] the current result of EURUSD.Ask[0] - AUDUSD.Bid[0]

 if (bbds >= Spread[0]) 
            {
                ExecuteMarketOrder(TradeType.Sell,"AUDUSD",100000);
                ExecuteMarketOrder(TradeType.Buy,"EURUSD",100000);

             }

Is it more or less clear ? If you need more information, please let me know.

Regards

David

***Note: if there is anyone closely following this post I am still looking for someone who could do this for me, of course, paid.

 


@david.sanchez

david.sanchez
27 Feb 2020, 11:03

RE:

Hi Panagiotis,

Excuse me, I did not mean to let you study my strategy or engage in custom development. I thought this was your expectation for my explanation of what I am trying to do.

I will try it soon.

Sincerely,

David 

 


@david.sanchez

david.sanchez
27 Feb 2020, 10:50 ( Updated at: 21 Dec 2023, 09:21 )

RE:

Hi Panagiotis,

This will be a long post because I want to describe and explain it as detailed as possible. Please stick with me because I am certain that solving this issue will be of great value for the community since forex markets have unique mathematical relationships between pairs. It is necessary to subtract, add, multiply or divide two or multiple pairs for analyzing those mathematical relationships. In my case I want to trade cross- pairs spread, which is the subtraction of two different pairs, EURUSD - AUDUSD for instance. So whenever I mention spread I am talking about these spreads: cross- pair spreads.

Note that this particular spread is nonsense it is just for illustration purposes. Imagine this spread would generate the attached charts at the end of this post.

there are three panels:

Panel 1 shows the result of EURUSD - AUDUSD (not really, just for the sake of the explanation) in green

Panel 1 shows the Bollinger bands on that spread in cyan

Panel 1 shows the SMA on that spread in pink

Panel 2 shows EURUSD, the first leg of the spread

Panel 3 shows AUDUSD, the second leg of the spread

*Those setups were created with multicharts.NET the entry and exits are marked with arrows.

As you can see the chart on panel 1, which is the cross pair spread itself, EURUSD - AUDUSD, goes sideways. This implements, that there is "no" significant risk on the up- nor on the downside. This makes this strategy market-neutral.

So the goal is to scalp the spread, selling when it is expensive, buying when it is cheap. 

Therefore a suitable indicator would be Bollinger bands since they add and subtract a given standard deviation on and from a simple moving average.

So if the current value of the spread is >= the upper bound then sell the spread and if the current value is <= the lower bound, buy it. 

Now selling the spread means: Sell EURUSD (the first leg) and buy AUDUSD (the second leg) because we want to hedge ourselves against market risk. And since we encountered a situation where the spread is overpriced it should reverse to its mean and we can "lock" profits. The beauty is, that is irrelevant how it returns to its mean or to the other extreme. Whether EURUSD goes up or AUDUSD goes down or something in between does not matter to us.

Sample: EURUSD = 4; AUDUSD = 2 => Spread value = 2 (EURUSD - AUDUSD); Sell the spread = Sell EURUSD and buy AUDUSD

Mean = 0 

If EURUSD down goes to 2 then 2 dollars profit with the short no profit or loss with the long = 2 Dollars of profit.

or 

If AUDUSD goes up to 4 Dollars then 2 Dollars profit with the long and nothing with the short.

on the charts, the trade is exited not when reaching the mean but actually when reaching the other side/ extreme of the Bollinger bands (from upper to lower bound and vice versa). This generates less commission.

Perfect isn't it?

There is no point in waiting for a close of a bar and since we want to get in as fast as possible (because we want both trades, Buy EURUSD and Sell AUDUSD, to happen simultaneously) we want to use market orders.

This brings a new dynamic into play. 

Buy Marketorders get executed at Ask prices and Sell Market orders at Bid prices.

So instead of just doing this: EURUSD - AUDUSD

We do this: Ask of EURUSD - Bid of AUDUSD

You probably noticed that it gets pretty complicated from here on because for buy trades we would need EURUSD.Ask - AUDUSD.Bid and for exit trades EURUSD.Bid - AUDUSD.Ask 

Because buying the spread is buying EURUSD at ask and selling AUDUSD at bid and selling the spread is seling EURUSD at bid and buying AUDUSD at ask.

All I need is to know is how to write the first part which is:

if  current value of (EURUSD.Ask - AUDUSD.Bid) is equal or greater than upper bound of Bollinger bands(EURUSD.Ask - AUDUSD.Bid) 

In my code above (last post) I seem to have been able to write everything correctly until the condition of the if method, there it shows an error:

"here it says that the logic operations cannot be applied to types of "Bollinger bands" and "double", How can I solve this?"

 

With the ability to use subtraction, addition, division and multiplication between two or more different pairs and then using that result in indicators and if statements we are able to explore a lot more trading possibilities because of the mathematical relationships in the forex markets which are unique to them. 

So bottom line: I want to subtract EURUSD.Ask from AUDUSD.bid and use that in the Bollinger bands indicator and for the logic of the if statement for entering and exiting trades with the <>= operations.

It would be really a pity if this potential stays unattainable.

I really really appreciate your time and your support.

Sincerely,

David Sanchez

***********************attachment***************************************************

compare the dates to find the identical trades.

Chart for first leg

chart for the second leg (note how it does the opposite of the first leg)


@david.sanchez

david.sanchez
26 Feb 2020, 21:23

RE: RE:

So I tried to use it but I still need some help

            //Am I supposed to write "AUDUSD" in here? How would it otherwise be clear from where to draw tick data?

            var ticks = MarketData.GetTicks("AUDUSD");
            var series = CreateDataSeries();
            int i = 0;
            foreach (var tick in ticks)
            {
                series[i] = tick.Ask;
                i++;
            }

            var ticks2 = MarketData.GetTicks("EURUSD");
            var series2 = CreateDataSeries();
            int t = 0;
            foreach (var tick in ticks)
            {
                series2[t] = tick.Bid;
                t++;
            }

            

           var Spread = CreateDataSeries();
           
            for (int X = 0; X < 10; X++)
            {
               
                Spread[X] = series[X] - series2[X];
               
            }


            var bbds = Indicators.BollingerBands(Spread, 10, 1, MovingAverageType.Simple);//upper Bollinger band
            var bbds2 = Indicators.BollingerBands(Spread, 10, -1, MovingAverageType.Simple)//lower Bollinger band

            /*up to here everything seems to work (no error messages)

            here it says that the logic operations cannot be applied to types of "bollinger bands" and "double", How can I solve this?*/

            if (bbds >= Spread[0]) 
            {
                ExecuteMarketOrder(TradeType.Sell,"AUDUSD",100000);
                ExecuteMarketOrder(TradeType.Buy,"EURUSD",100000);

                ...

            }

I would be very grateful if you could help me on this last issue...

Sincerely,

David Sanchez


@david.sanchez

david.sanchez
26 Feb 2020, 10:51

RE:

Hi Panagiotis,

Alright, this looks like all the pieces I need.

Thank you a lot!

Have a nice day!

David

 

 


@david.sanchez

david.sanchez
26 Feb 2020, 10:35

RE:

Hi Panagiotis

Yes, I contacted two professionals who offer coding services for ctrader. 

The first one declined my offer due to reasons which they did not tell me ( I did not demand a certain price).

The second one did not understand what a cross- pair spread is.

Now, I probably found a sample which looks like what I need 

Can I use  this "var _s2 = MarketData.GetSeries("EURUSD", TimeFrame)" to get bid/ask values of certain symbols?

Best Regards

Panagiotis


@david.sanchez

david.sanchez
26 Feb 2020, 10:09

RE:

 

Hi Panagiotis,

Thank you for your response.

Can I just change the datatype from "var" to "DataSeries"?

2) I will take a look on that, thank you!

Sincerely,

David Sanchez


@david.sanchez

david.sanchez
25 Feb 2020, 21:30

RE: RE:

Hi Panagiotis,

Your Code helped a lot but I am not quite there.

Below you find everything the strategy will do.

However, it seems as if the cross pair spread is not usable for the Bollinger bands indicator.

How can I use it as intended below? 

In addition, is it possible to close and open positions in both instruments from the code as I tried below?

I would be very grateful if you could help me further on this issue.

If you need more information please let me know.

Sincerely,

David

using System;
using System.Linq;
using System.Collections.Generic;
using cAlgo.API;
using cAlgo.API.Requests;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
using cAlgo.Indicators;

namespace cAlgo
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class Arbitrage1 : Robot
    {
       
      
        private BollingerBands bbds;

        protected override void OnStart()
        {
            var symbol1 = Symbols.GetSymbol("AUDUSD");
            var symbol2 = Symbols.GetSymbol("EURUSD");
            var spread = symbol1.Ask - symbol2.Bid;
            
            bbds = Indicators.BollingerBands(spread, 10,1,MovingAverageType.Simple);
    
        }
        protected override void OnTick()
        {
            
            var symbol1 = Symbols.GetSymbol("AUDUSD");
            var symbol2 = Symbols.GetSymbol("EURUSD");
            var spread = symbol1.Ask - symbol2.Bid;
            
            bbds = Indicators.BollingerBands(spread, 10,1,MovingAverageType.Simple);
            
            if (bbds >= spread) 
            {
                ExecuteMarketOrder(TradeType.Sell,"AUDUSD",100000);
                ExecuteMarketOrder(TradeType.Buy,"EURUSD",100000);
                
                if (position("AUDUSD") > 0)
                {
                    ClosePosition(?);
                }
                else if (Position("EURUSD") < 0)
                {
                    ClosePosition();
                }
                
            }
            else if (bbds <= spread)
            {
                ExecuteMarketOrder(TradeType.Buy,"AUDUSD",100000);
                ExecuteMarketOrder(TradeType.Sell,"EURUSD",100000);

                if (position("AUDUSD") < 0)
                {
                    ClosePosition(?);
                }
                else if (Position("EURUSD") > 0)
                {
                    ClosePosition();
                }
            }
                
        }
    }
}

 


@david.sanchez

david.sanchez
24 Feb 2020, 10:41

RE:

PanagiotisCharalampous said:

Hi David,

See below

            var symbol1 = Symbols.GetSymbol("AUDUSD");
            var symbol2 = Symbols.GetSymbol("EURUSD");
            var spread = symbol1.Ask - symbol2.Bid;

Best Regards,

Panagiotis 

Join us on Telegram

 

wow, Thank you I will try it soon!


@david.sanchez

david.sanchez
24 Feb 2020, 10:01

RE:

Here you find the code I am trying to implement.

 

What am I doing wrong? 

How can I create a cross- pair spread (AUDUSD.ask - EURUSD.bid)?

 

using System;
using System.Linq;
using System.Collections.Generic;
using cAlgo.API;
using cAlgo.API.Requests;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
using cAlgo.Indicators;

namespace cAlgo
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class Hedging2positionsonly : Robot
    {

        [Parameter("Max Spread", DefaultValue = 0.0, MinValue = -5.0)]
        public double MaxSpread { get; set; }

        string label = "Spread Test";

        protected override void OnStart()
        {
            var leg1 =public Symbol GetSymbol("AUDUSD");
            var leg2 =public Symbol GetSymbol("EURUSD");
            Spread = AUDUSD.Ask - EURUSD.Bid

    
        }

 


@david.sanchez

david.sanchez
19 Feb 2020, 10:25

RE:

Hi Panagiotis

Thank you for your response.

I think I just typed in EURUSD in the field but I am not sure anymore.

Below you find what I am trying to achieve, it is code written for Multicharts, which I am trying to "translate".

BarsOfData(1) is for instance data from EURUSD.

I will recreate my code this week and will come back to you with a sample.

Sincerely,

David 

 

Multicharts code********************************************************************************

using System;
using System.Drawing;
using System.Linq;
using PowerLanguage.Function;
using ATCenterProxy.interop;

namespace PowerLanguage.Strategy {
	public class ArbitrageMaster2 : SignalObject {
		public ArbitrageMaster2(object _ctx):base(_ctx)
		{
			Length = 10;
			Std = 1;
		}
		//All the Inputs needed are here
		[Input]
		public int Length { get; set; }
		[Input]
		public int Std { get; set; }

		private VariableSeries<Double> Ratio;
		private ISeries<double> b_Seriesdiff;



		private IOrderMarket m_long;
		private IOrderMarket m_short;
		private IOrderMarket m_lx;
		private IOrderMarket m_sx;

		//This function is for creating objects, note that market this bar is taken because once the spread is wide enough I want to enter the trade ASAP
		protected override void Create() 
		{
			Ratio = new VariableSeries<double>(this);
			

			m_long = OrderCreator.MarketThisBar(new SOrderParameters(Contracts.Default, EOrderAction.Buy));
			m_short = OrderCreator.MarketThisBar(new SOrderParameters(Contracts.Default, EOrderAction.SellShort));

			m_lx = OrderCreator.MarketThisBar(new SOrderParameters(Contracts.Default, EOrderAction.Sell));
			m_sx = OrderCreator.MarketThisBar(new SOrderParameters(Contracts.Default, EOrderAction.BuyToCover));
		}
		//This function initializes the first calculation
		protected override void StartCalc() 
		{
			b_Seriesdiff = new Lambda<Double>((_bb => ((BarsOfData(2).Close[_bb] - BarsOfData(1).Close[_bb]))));
		}

		//strategy logic is here, -std is the lower bound of the bollinger bands it is the standarddeviation which gets substracted from the mean
		protected override void CalcBar()
		{

			double oBB = b_Seriesdiff.BollingerBandCustom(Length, Std);
			double uBB = b_Seriesdiff.BollingerBandCustom(Length, -Std);

			Ratio.Value = BarsOfData(2).CloseValue - BarsOfData(1).CloseValue;

			if (Ratio.Value <= uBB)
			{
				m_short.Send();
				m_lx.Send();
			}

			if (Ratio.Value >= oBB)
			{
				m_long.Send();
				m_sx.Send();
			}
		}
	}
}

 


@david.sanchez