Error connecting R to cAlgo via R.NET

Created at 07 Sep 2015, 14:25
How’s your experience with the cTrader Platform?
Your feedback is crucial to cTrader's development. Please take a few seconds to share your opinion and help us improve your trading experience. Thanks!
IN

IncubusI

Joined 07.09.2015

Error connecting R to cAlgo via R.NET
07 Sep 2015, 14:25


Hi,

I am trying to connect cAlgo to R using R.NET library. I use R.NET in many of my other projects and since now did not have a problem using it. 

What happens when I try to use it with cAlgo is that it just does not want to initialize R session. The program doesn't print any error or exception it just seems that it runs in some loop trying to connect to R but fails. I tried it on several different computers and also with different R versions. 

I also set access rights in cAlgo to FullAccess. Couple of times I managed to get R running and it was when cAlgo asked me whether I want to allow indicator to have unlimited access rights. I click allow and only then R is running normally. But when I do it the second time cAlgo doesn't ask me anything regarding access rights and R cannot initialize. 

I have been struggling with this for some time now and I would really appreciate any help and suggestions from your side. 

Thanks in advance!

 

 

 


@IncubusI
Replies

ClickAlgo
07 Sep 2015, 15:03

Is this what you are using?

https://rdotnet.codeplex.com/documentation


@ClickAlgo

IncubusI
07 Sep 2015, 15:04

RE:

Paul_Hayes said:

Is this what you are using?

https://rdotnet.codeplex.com/documentation

 

Yes


@IncubusI

ClickAlgo
07 Sep 2015, 15:26

ok, has it been working before and has it now suddenly stopped working or is this a new project?

Have you got it working with the cAlgo API before?


@ClickAlgo

ClickAlgo
07 Sep 2015, 15:42

I would make sure you have a reference to the source code of R.Net in your project and not just the assembly, debug the code in Visual Studio and step into R.Net when it initializes, take a look at where goes and if an exception occurs, you could also create a basic test where all the code does is connect a new session with R.NET and that's all.


@ClickAlgo

IncubusI
07 Sep 2015, 16:06

RE:

Paul_Hayes said:

ok, has it been working before and has it now suddenly stopped working or is this a new project?

Have you got it working with the cAlgo API before?

It is a new project. I have not used R (R.NET) with cAlgo before. Have you ever tried using R with cAlgo? 
It works only the first time when I make a new indicator. After that it fails every time. 

Also I have tried to put R.NET source as reference and debug it but didn't come up with anything useful.


@IncubusI

ClickAlgo
07 Sep 2015, 17:22

No I have not used it before, but it looks useful, I am trying to get the basic example working with a cAlgo cBot, I have referenced from NuGet:-

Collaboration of .NET Framework with R statistical computing

You will not be able to debug an indicator over the weekend as you have no data feeds, you can back-test with a cBot to debug with visual studio.

If you have got it working and it only worked first time then it could be because the engine has not been shut down, have you tried:-

engine.Dispose();

I am not sure how cAlgo releases memory in an indicator, but in a cBot its OnStop, anyway try and destroy the engine and see if that helps.

Could you send me your initialization code and I may be able to debug deeper and find the issue for you.


@ClickAlgo

ClickAlgo
07 Sep 2015, 17:24

RE:

Sorry, i meant to say that a method is called when an event is fired to close the cBot or indicator, this is where you want to release the handle on the R.NET engine, it may not be the answer, but its worth a try.


@ClickAlgo

IncubusI
07 Sep 2015, 18:15

Paul I am sending the code of my indicator. 

You can even disregard the Calculate() function since the code never reaches it. It fails at r = REngine.GetInstance(); Also disregard the while(true) loop - its just there because I was trying to catch where it fails and why isn't R running.

Here are the steps how I am running the program:

1. Edit the code in visual studio

2. Attach to the process cAlgo

3. Add instance 

 

Try it out for yourself and see how it works for you. Also you should use 1.6.5.0 version of R.NET (I don't know which one you downloaded from NuGet).

Thank you for helping out, its really frustrating since I am dealing with this issue for a long time now and I am running out of options and ideas.

 

using System;
using cAlgo.API;
using cAlgo.API.Internals;
using cAlgo.API.Indicators;
using cAlgo.Indicators;
using RDotNet;
using System.IO;
using Microsoft.Win32;

namespace cAlgo
{
    [Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.FullAccess)]
    public class indicator : Indicator
    {
        [Parameter(DefaultValue = 0.0)]
        public double Parameter { get; set; }

        [Output("avg")]
        public IndicatorDataSeries avg { get; set; }

        private static REngine r;

        private string rBinPath { get; set; }

        protected override void Initialize()
        {
            // Initialize and create nested indicators
            using (RegistryKey registryKey = Registry.LocalMachine.OpenSubKey("SOFTWARE\\R-       core\\R"))
            {
                var envPath = Environment.GetEnvironmentVariable("PATH");
                rBinPath = (string)registryKey.GetValue("InstallPath");
                string rVersion = (string)registryKey.GetValue("Current Version");
                rBinPath = System.Environment.Is64BitProcess ? rBinPath + "\\bin\\x64" : rBinPath + "\\bin\\i386";
                Environment.SetEnvironmentVariable("PATH", envPath + Path.PathSeparator + rBinPath);
            }
            while (true)
            {
                try
                {
                    REngine.SetEnvironmentVariables(rBinPath);
                    r = REngine.GetInstance();
                    if (r.IsRunning)
                    {
                        break;
                    }
                    else
                    {
                        r.Initialize();
                    }
                } catch (Exception ex)
                {
                    Print("Error:" + ex.ToString());
                }
            }
        }

        public override void Calculate(int index)
        {
            // Calculate value at specified index
            // Result[index] = ...
            double open = MarketSeries.Open[index];
            double high = MarketSeries.High[index];
            double low = MarketSeries.Low[index];
            double close = MarketSeries.Close[index];

            avg[index] = avgPrice(open, high, low, close);
        }

        private double avgPrice(double open, double high, double low, double close)
        {
            r.SetSymbol("open", r.CreateNumeric(open));
            r.SetSymbol("high", r.CreateNumeric(high));
            r.SetSymbol("low", r.CreateNumeric(low));
            r.SetSymbol("close", r.CreateNumeric(close));
            NumericVector avg = r.Evaluate("(open + high + low + close)/4").AsNumeric();
            return (Convert.ToDouble(avg[0]));
        }
    }
}

 


@IncubusI

ClickAlgo
07 Sep 2015, 18:25

ok, i will take a look


@ClickAlgo

ClickAlgo
07 Sep 2015, 18:39

Did you install the R.NET other than with NuGet?

How did you setup your registry values?


@ClickAlgo

IncubusI
07 Sep 2015, 18:42

RE:

Paul_Hayes said:

Did you install the R.NET other than with NuGet?

How did you setup your registry values?

Yes. I tried installing R.NET from source too but it didn't help.

What do you mean by registry values?


@IncubusI

ClickAlgo
07 Sep 2015, 18:55

Run this, tell me if it states in the log Initialized and then disposed or if it fails again.

protected override void Initialize()
        {
            RegistryKey registryKey = Registry.LocalMachine.OpenSubKey("SOFTWARE\\R-core\\R");

            var envPath = Environment.GetEnvironmentVariable("PATH");
            rBinPath = (string)registryKey.GetValue("InstallPath");
            string rVersion = (string)registryKey.GetValue("Current Version");
            rBinPath = System.Environment.Is64BitProcess ? rBinPath + "\\bin\\x64" : rBinPath + "\\bin\\i386";
            Environment.SetEnvironmentVariable("PATH", envPath + Path.PathSeparator + rBinPath);

            REngine.SetEnvironmentVariables(rBinPath);
            r = REngine.GetInstance();

            r.Initialize();
            Print("Initialized...");

            // close engine
            r.Dispose();
            Print("Disposed...");
        }

 


@ClickAlgo

IncubusI
07 Sep 2015, 19:13

RE:

Paul_Hayes said:

Run this, tell me if it states in the log Initialized and then disposed or if it fails again.

protected override void Initialize()
        {
            RegistryKey registryKey = Registry.LocalMachine.OpenSubKey("SOFTWARE\\R-core\\R");

            var envPath = Environment.GetEnvironmentVariable("PATH");
            rBinPath = (string)registryKey.GetValue("InstallPath");
            string rVersion = (string)registryKey.GetValue("Current Version");
            rBinPath = System.Environment.Is64BitProcess ? rBinPath + "\\bin\\x64" : rBinPath + "\\bin\\i386";
            Environment.SetEnvironmentVariable("PATH", envPath + Path.PathSeparator + rBinPath);

            REngine.SetEnvironmentVariables(rBinPath);
            r = REngine.GetInstance();

            r.Initialize();
            Print("Initialized...");

            // close engine
            r.Dispose();
            Print("Disposed...");
        }

 

It only worked the first time. I created a new indicator with this code. It worked. R was running and then stopped with dispose, but second time I tried to run it it failed again like in previous cases.


@IncubusI

ClickAlgo
07 Sep 2015, 23:18

I think the problem is where cAlgo runs in a sandbox and your calling a In-Process COM object through Interop, the reference stays in memory even if you close the instance.

You may be able to get it to work, i don't know, but I will keep trying as I think it would be pretty cool to use the R.NET, but it may crash cAlgo if it is not coded correctly.

There is another way which is for your cBot to run in its little playhouse and it calls a standalone windows service with a generic protocol which will do the number crunching with R.NET and returns the values to the cBot.


@ClickAlgo

ClickAlgo
08 Sep 2015, 09:20

I am creating a WCF Service Application to run under IIS and you just add a service reference to your cAlgo project, you will not need any references to R.NET in cAlgo, all the logic will be in the service and you just expose your methods for calculations, , I will try and get it working on my web server and give you the service address.

You would use it like this:-

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.FullAccess)]
    public class indicator : Indicator
    {
        [Parameter(DefaultValue = 0.0)]
        public double Parameter { get; set; }

        [Output("avg")]
        public IndicatorDataSeries avg { get; set; }

        rService.RServiceClient r;

        protected override void Initialize()
        {
            r = new rService.RServiceClient();
        }

        public override void Calculate(int index)
        {
            // Calculate value at specified index
            // Result[index] = ...
            double open = MarketSeries.Open[index];
            double high = MarketSeries.High[index];
            double low = MarketSeries.Low[index];
            double close = MarketSeries.Close[index];

            if(r != null)
            {
                avg[index] = r.GetAvgPrice(open, high, low, close);
                Print(avg[index].ToString());
            }
                
        }
    }
}

Will give you  a shout when I have it working.


@ClickAlgo