Dukascopy Support Board
http://www.dukascopy.com/swiss/english/forex/jforex/forum/

ILocalStrategyManager errors on compile / start strategy methods
http://www.dukascopy.com/swiss/english/forex/jforex/forum/viewtopic.php?f=16&t=57769
Page 1 of 1

Author:  degeorge [ Sun 16 Jan, 2022, 21:19 ]
Post subject:  ILocalStrategyManager errors on compile / start strategy methods

Hi!
What i'am trying to achieve: run plugin inside terminal app, which would internally start IStrategy instance(s). But I see some strange behaviour, looks like a bug :)
JForex version: 3.6.42
JForex API version: 2.13.98
OS: macOS 12.1

Reproducing:
1. Save this code as jforex terminal plugin with file name as TestPlugin.java:
package jforex;

import com.dukascopy.api.IConsole;
import com.dukascopy.api.JFException;
import com.dukascopy.api.JFXInject;
import com.dukascopy.api.plugins.IPluginContext;
import com.dukascopy.api.strategy.IStrategyResponse;
import com.dukascopy.api.strategy.local.ILocalStrategyDescriptor;
import com.dukascopy.api.strategy.local.ILocalStrategyManager;
import com.dukascopy.api.strategy.local.LocalStrategyListener;

import java.io.File;
import java.nio.file.Paths;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

public class TestPlugin extends com.dukascopy.api.plugins.Plugin {

    @JFXInject
    public IConsole console;

    @Override
    public void onStart(IPluginContext context) throws JFException {
        try {
            console.getOut().println("Plugin started!");

            final ILocalStrategyManager localManager = context.getLocalStrategyManager();
            localManager.addStrategyListener(new LocalStrategyListener() {
                @Override
                public void onStrategyRun(ILocalStrategyDescriptor strategyDescriptor) {
                    console.getOut().printf("Strategy successfully started! Descriptor: %s%n", strategyDescriptor);
                }

                @Override
                public void onStrategyStop(ILocalStrategyDescriptor strategyDescriptor) {
                    console.getOut().printf("Strategy stopped. Descriptor: %s%n", strategyDescriptor);
                }
            });

            final String javaStratFileName = "DemoStrategy.java";
            final String jfxStratFileName = "DemoStrategy.jfx";

            // loadableDir will be used to store DemoStrategy.java file and compiled output for it
            final File loadableDir = context.getFilesDir();
            // create abs path for strategy (java file)
            final File strategyFile = Paths.get(loadableDir.getAbsolutePath(), javaStratFileName).toFile();
            // this will compile java -> jfx, but result is null, while compiled file exists
            final File jfxRes = localManager.compileStrategy(strategyFile);
            if (jfxRes == null) {
                console.getOut().println("Compiled jfx file is null");
            }
            // workaround for null exception - manually create path to compiled jfx file
            final File jfxFile = Paths.get(loadableDir.getAbsolutePath(), jfxStratFileName).toFile();
            console.getOut().printf("Path: %s%n", jfxFile.getAbsolutePath());

            // startStrategy method always throw Timeout exception, but strategy is started (without specified timeout, it will wait...)
            final IStrategyResponse<UUID> response = localManager.startStrategy(jfxFile).get(10000, TimeUnit.MILLISECONDS);
            if (response.isError()) throw new Exception(response.getErrorMessage());
            console.getOut().printf("Strategy started. ID: %s%n", response.getResult());

        } catch (Exception e) {
            e.printStackTrace(console.getErr());
            context.stop();
        }
    }

    @Override
    public void onStop() throws JFException {
        console.getOut().println("Plugin stopped!");
    }
}


2. Save the code below in file called 'DemoStrategy.java' inside loadableDir (look at variable inside plugin code):
package jforex;

import com.dukascopy.api.*;

public class DemoStrategy implements IStrategy {
    @JFXInject
    public IConsole console;

    @Override
    public void onStart(IContext context) throws JFException {
        try {
            console.getOut().println("Strategy started!");
            // making some work for 3 secs
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace(console.getErr());
        } finally {
            context.stop();
        }
    }

    @Override
    public void onTick(Instrument instrument, ITick tick) throws JFException {

    }

    @Override
    public void onBar(Instrument instrument, Period period, IBar askBar, IBar bidBar) throws JFException {

    }

    @Override
    public void onMessage(IMessage message) throws JFException {

    }

    @Override
    public void onAccount(IAccount account) throws JFException {

    }

    @Override
    public void onStop() throws JFException {
        console.getOut().println("Strategy stopped!");
    }
}


3. Activate plugin

Expected: Successfully started strategy without some kind of exceptions.

I have two issues in this code:
1. ILocalStrategyManager.compileStrategy(io.File java_file) - return null for io.File instance, while compilation is successfull -> I expected it will return io.File for compiled DemoStrategy.jfx file.
2. ILocalStrategyManager.startStrategy(io.File jfx_file) - return instance of java Future that never completes, while strategy is started successfully and manager callback (LocalStrategyListener) is invoked -> I expected future would successfully completed after some time.

Thanks.

Author:  vadim_berezhnoj [ Wed 26 Jan, 2022, 11:40 ]
Post subject:  Re: ILocalStrategyManager errors on compile / start strategy methods

Hello.

1. ILocalStrategyManager.compileStrategy() returns null while compilation is successful - will be fixed in next platform release.

2. ILocalStrategyManager.startStrategy() returns Future that never completes - this issue occurs when strategy is stopped in IStrategy.onStart() method.
In next platform release, "Strategy stopped while starting!" error will be returned in such case.

Regard.

  Page 1 of 1