Use second plot as input ?

Spin

Well-known member
Joined
May 22, 2019
Posts
505
Likes
211
Hello there fellow coders :)

It's been a while that I launched a thread of my own, but I am afraid the time has come. Again :D

I am looking to use the 'values' or 'data' from a secondary plot to use in calculations.
More specifically, I would like to add fractals to a second Study
Fractals are calculated like so:
Java:
List<SwingPoint> swingPoints = series.calcSwingPoints(getSettings().getInteger(Inputs.STRENGTH, 2));

so I need to create a secondary series that holds the data from a 'Study B'
OR
I need to figure out a way to use calcSwingPoints on the data/values of Study B (Study B stores floats for Open, High, Low, Close to the dataseries)

Did anyone on this expert forum try something similar before ?
What would be a good way to tackle this ?

Thanks for all hints, tips & snippets !! (y)
 
Last edited:
Yep, but it took me several coding hours:
I dove in a few rabbit holes first, to no avail (see below).
And then I realized that good advice that @MotiveWave_Joe once gave me, and put all of the logic into a single study.
https://support.motivewave.com/foru...ing-values-in-a-different-study.273/post-1103

A few of the rabbit holes (that did NOT work):
(I need to add here that Studies A and B both 'live' in a different Plot: A is calculated on Price, B is some sort of oscillator that takes volume into account and is drawn on a secondary plot)

  • tried to create a secondary DataSeries on the primary plot, to hold data from a different Study
    (I don't think this can be done ?)
  • export Values from Study A to DataSeries and import them into Study B
    (apparently each 'window' uses a different DataSeries, although values from both are shown in the Cursor Data Window, seemingly identical; who can shed light onto this ? :unsure:)
  • export Values from Study A to DataSeries and have a 'ulility'-class-method read them from within Study B
    (tried something similar to what STARC-bands does with Bollinger Bands - epic fail, hit the same wall)
  • save Values from Study A to a file and have Study B read them from that file
    (somewhat worked, but laggy)
  • thought of this, but did not try it in the end: store Values from A in a Redis-DB and have B read from it
    (should work imo, and faster too)
But the end result is this:
I drop Study B and have it draw markers on the secondary plot.
I drop Study A, that now holds (part of) the code from Study B, so it calculates the same oscillator / volume thing. Does not draw anything, since I only need the Values.
In Study A I added logic to draw BUY / SELL arrows; this logic uses Values from both Studies A and B.
(sorry for the pixelation; I am not allowed to share details :cool:)
1670011209295.png
 
Last edited:
Yeah that's what I sort of assumed. I had to update one of the indicators and decorate it with something else so I had to do it in one place, like you did.

I think it doesn't yet mean it is impossible, just that we don't know how to. It would be rather sad if this use case isn't covered because it would severely limit complex studies.
 
I fully agree, @Per !

And since everything is written to the DataSeries anyway, it shouldn't be too hard, no ? :unsure:
 
Hi there, I might be a little late with my answer, but I found a somewhat usable way of dealing with sharing calculations between studies.

I solved this by creating a singleton class "DataContainer". This container contains a Map where I store my calculations for a given candleIndex. As this is a singleton-pattern, I can reuse this in every study and read from that Map. A Utilty-Class with helper methods allows me to easily write into the series cursorData (eg. series.setXX(..)) and into my map to share the calculations.

This works quite well, but it has one big downside :( I currently can't control the execution order of the studies. My plan is to have multiple studies that calculate something and one big study as a "MasterStudy" that makes decisions based on the calculations of the other studies. But, I can't figure out how to define that the MasterStudy should run after ALL of the other studies finished their calculation. I tried keeping a list of studies that I depend on and having a while-loop in precalculate to wait for the other studies to finish (hoping that the studies are calculated parallel), but that did not work, as the studies are not calculated in parallel, but one after another.

Updating the study with the "Update" Button proves, that my approach is working. I can read the values from the Map. But I don't want to press update all the time, but have the MasterStudy be executed at the last study.

If there only would be a way to define a execution order. That would solve my issue. There is nothing like this documented in the Motivewave SDK javadoc.
 
Hi there, I might be a little late with my answer, but I found a somewhat usable way of dealing with sharing calculations between studies.

I solved this by creating a singleton class "DataContainer". This container contains a Map where I store my calculations for a given candleIndex. As this is a singleton-pattern, I can reuse this in every study and read from that Map. A Utilty-Class with helper methods allows me to easily write into the series cursorData (eg. series.setXX(..)) and into my map to share the calculations.

This works quite well, but it has one big downside :( I currently can't control the execution order of the studies. My plan is to have multiple studies that calculate something and one big study as a "MasterStudy" that makes decisions based on the calculations of the other studies. But, I can't figure out how to define that the MasterStudy should run after ALL of the other studies finished their calculation. I tried keeping a list of studies that I depend on and having a while-loop in precalculate to wait for the other studies to finish (hoping that the studies are calculated parallel), but that did not work, as the studies are not calculated in parallel, but one after another.

Updating the study with the "Update" Button proves, that my approach is working. I can read the values from the Map. But I don't want to press update all the time, but have the MasterStudy be executed at the last study.

If there only would be a way to define a execution order. That would solve my issue. There is nothing like this documented in the Motivewave SDK javadoc.


I am not a professional programmer, but when you mention about creating a singleton, is it something similar to HashMap, but it is immutable? I did some research, and found a bunch of website that give examples about HashMaps:


Let's say, I have 2 different studies: One of them is RSI (study 1), the other is MACD (study 2). I want to store the last two bars' RSI values in a hashmap, then get these values inside the MACD study.

Java:
import java.util.HashMap;

public class Study1 extends com.motivewave.platform.sdk.study.Study {
    
    // Declare HashMap to store RSI values
    private HashMap<String, Double> rsiValues = new HashMap<>();

    @Override
    public void calculate() {
        // Calculate RSI value for the current bar
        double currentRSI = calculateRSI(); // Replace this with your RSI calculation logic
        
        // Store RSI value of the last bar in the HashMap
        rsiValues.put("lastBarRSI", currentRSI);
        
        // Optionally, store RSI value of the bar preceding the last bar
        double precedingRSI = calculatePrecedingRSI(); // Implement this method to calculate RSI of the preceding bar
        rsiValues.put("precedingBarRSI", precedingRSI);
    }
    
    // Method to retrieve RSI values HashMap
    public HashMap<String, Double> getRSIValues() {
        return rsiValues;
    }
}

And the study 2 should be able to retrieve these HashMap values from the study 1.
Java:
public class Study2 extends com.motivewave.platform.sdk.study.Study {
    
    @Override
    public void calculate() {
        // Get instance of Study 1
        Study1 study1 = (Study1) getContext().getStudy("Study1");
        
        // Retrieve RSI values HashMap from Study 1
        HashMap<String, Double> rsiValues = study1.getRSIValues();
        
        // Get last bar's RSI value
        double lastBarRSI = rsiValues.get("lastBarRSI");
        
        // Optionally, get RSI value of the bar preceding the last bar
        double precedingBarRSI = rsiValues.get("precedingBarRSI");
        
        // Use the retrieved RSI values as needed
    }
}

I used ChatGPT here just to give an example. I get correct hashmap values in study 1, but somehow the study 2 cannot retrieve these values from the study 1. However, even I am successful, this mean that I will have a similar problem like yours, as the calculation time for the study 1 will be different than the study 2, so it won't work?

Otherwise, I was able to export these values into a .csv file (again, only the last 2 bar's RSI values for example, not the whole Data Series), but when the csv file is read by the study 2, it gives an "ArrayIndexOutOfBoundsException" error. Although I did not have any calculation problem, this error was weird, because I verified that the number of Array Elements was less than or equal to the length of the array. Anyway.

I think the best approach would be using Redis or MySQL as @Spin suggested in other posts. But I am bit lazy, since I only want to export last two bar's values from a given study.

I am open to your suggestions. Thank you.
 
Hi @HalTrader, I am talking about a singleton class with only one instance that can be used with all Studies:
Java:
public final class DataContainer {

    private Map<Integer, Map<String, Object>> candleValues = new HashMap<>();

    private static DataContainer instance;

    private DataContainer() {}

    public static DataContainer getInstance() {
        if (instance == null) {
            instance = new DataContainer();
        }
        return instance;
    }

    // remaining code
}

You can then save something into that Container by calling "DataContainer.getInstance.THEMETHODYOUWANTTOCALL".
As the DataContainer is a singleton and therefore only exists once, each study is using the same java object.

Redis or MySQL is in my opinion just a different way of doing the same that I did with the DataContainer, but the Java Singleton is much (!) easier to do.
But, regardless which way you choose (Singleton, Database, ...) - we will always have the issue with the execution order of the studies. Saving the calculations is not the problem.

We have to figure out how MotiveWave decides the execution order - if we know this, we can share calculations from Study A to Study B without any problems.
 
Good thinking, @Dennis and @HalTrader ! :)

I too have fiddled with the same problem over and over. I even had 'timers' built in to Studies, so one would run on barOpen + 10 seconds, the next +30 seconds and so on. But those are just workarounds, and do not really tackle the root cause of this issue.

I will be monitoring this thread, and try to help out when I can. The singleton is a good idea, and perhaps JAVA's 'Thread' might help you guys along.
It allows to get the ID and Name of a thread. I would try those first to lift the fog and see what's going on. After that you could perhaps use 'yield' or 'sleep' or get/set the priority of a thread.

https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Thread.html
 
Good thinking, @Dennis and @HalTrader ! :)

I too have fiddled with the same problem over and over. I even had 'timers' built in to Studies, so one would run on barOpen + 10 seconds, the next +30 seconds and so on. But those are just workarounds, and do not really tackle the root cause of this issue.

I will be monitoring this thread, and try to help out when I can. The singleton is a good idea, and perhaps JAVA's 'Thread' might help you guys along.
It allows to get the ID and Name of a thread. I would try those first to lift the fog and see what's going on. After that you could perhaps use 'yield' or 'sleep' or get/set the priority of a thread.

https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Thread.html
Just tried printing the current ThreadID and ThreadName for each Study and also added debug messages for each pre-/post- and calculate-step.
They share the same Thread and are running in series. Study B starts when Study A finishes.
 
There is also another solution. See the link below:

In brief, "InputDescriptor" can be used to import an input series from the Cursor Data Window. Then, I think it should be possible to save them into different DataSeries in another study, and use them with "onBarOpen" or "onBarUpdate" to trigger a signal/condition that is dependent on values from both studies.

A few months ago, I imported Cursor Data Window values from one study to another study using this approach, but I never tried to create a condition that triggers alerts. It might be interesting to test it.
 
The InputDescriptor is not the right way for doing it the way that I imagine.

First of all, it doesn't list all of the other CursorData Values, just "Open,High,Low,Close,Midpoint,Typical Price,Weighted Price" - I assume this is due to the pricing plans of MotiveWave (I am using the free version).
Secondly, I would have to create a InputDescriptor for every value I want to consider - 10 values -> 10 InputDescriptors, 50 values -> 50 InputDescriptors.

I already have found a solution for that with my Singleton-Map-Approach and it is working great! - it's just that I currently can't control the execution order of my studies.

One simple example:
  1. Study A depends on calculations (CursorData Values) from Study B.
  2. MotiveWave decides, that Study A is executed first. Study B did not run yet and didn't calculate anything.
  3. Study A doesn't have any values from Study B and throws a NPE for simplicity.
  4. Study A is finished. Now MotiveWave is triggering Study B.
  5. Study B calculates everything and writes the values to CursorData and my DataContainer.
  6. If I now manually click on "update" in the SettingsWindow of Study A, Study A recalculates everything, it now has all of the calculations from Study B and can work with the values from Study B. No NPE anymore.
What do I want?
If I could control the execution order of my studies, I would first trigger Study B (and Study C, Study D, ...) and after all of my "calculate"-Studies are finished, I want to trigger Study A as the "brain"-Study as the last Study.
 
I have the Ultimate version and the InputDescriptor always shows OHLC, Midpoint, TP, WP values + custom DataSeries written by the user. But I totally agree on the fact that it is not user-friendly to create 10 values from 10 different InputDescriptors. There must be an easier way.
Otherwise, as @Spin suggested, another solution would be using Java's thread. I am not a programming or Java expert, but I wonder whether Java's thread can be used to control the execution order of your studies B, C, D, E and so on, then make sure that all the calculations from these studies are complete and study A is ready to process calculated DataSeries from other studies.

If someone finds a way to circumvent this problem, and posts a code example here, it would be great. I want to write a complex strategy in the future, where I combine DataSeries from multiple studies, then get all these values in a single strategy, similar to your study A, or the brain study. This strategy should receive all the DataSeries properly, process and open trades, and do trade management: send a limit order if conditions A, B, C are true. Then the limit order must be active as long as the conditions D and E are true, and cancel the limit order if the condition F is true, etc... I already found some code examples to write a simple Strategy, but managing the execution order of studies is a problem as you highlighted.
 
I have the Ultimate version and the InputDescriptor always shows OHLC, Midpoint, TP, WP values + custom DataSeries written by the user. But I totally agree on the fact that it is not user-friendly to create 10 values from 10 different InputDescriptors. There must be an easier way.
Otherwise, as @Spin suggested, another solution would be using Java's thread. I am not a programming or Java expert, but I wonder whether Java's thread can be used to control the execution order of your studies B, C, D, E and so on, then make sure that all the calculations from these studies are complete and study A is ready to process calculated DataSeries from other studies.

If someone finds a way to circumvent this problem, and posts a code example here, it would be great. I want to write a complex strategy in the future, where I combine DataSeries from multiple studies, then get all these values in a single strategy, similar to your study A, or the brain study. This strategy should receive all the DataSeries properly, process and open trades, and do trade management: send a limit order if conditions A, B, C are true. Then the limit order must be active as long as the conditions D and E are true, and cancel the limit order if the condition F is true, etc... I already found some code examples to write a simple Strategy, but managing the execution order of studies is a problem as you highlighted.
(I will say this quietly, to not stir up too much emotions 😄)

Perhaps create one biiiiiiiiiiiig package with in it a 'MASTER'-Study that calls the others in the correct order ?
 
(I will say this quietly, to not stir up too much emotions 😄)

Perhaps create one biiiiiiiiiiiig package with in it a 'MASTER'-Study that calls the others in the correct order ?
I already thought about something similar: creating static methods for the calculation in each study and then calling these in my desired order in my main study.. But I hoped that there is a better way 😅

Or not making them static and trying to creating new study instances with the DataContext from the main study.
 
I already thought about something similar: creating static methods for the calculation in each study and then calling these in my desired order in my main study.. But I hoped that there is a better way 😅

Or not making them static and trying to creating new study instances with the DataContext from the main study.
As it seems there is no great solution for that.
So I created my own - possible overkill - solution that gives me full flexibility and full control over all of my studies :) And I also found out in which order MotiveWave executes the studies, so no blocking topics for me anymore 🎉
 
Last edited:
As it seems there is no great solution for that.
So I created my own - possible overkill - solution that gives me full flexibility and full control over all of my studies :) And I also found out in which order MotiveWave executes the studies, so no blocking topics for me anymore 🎉
You use some kind of "external to MW" storage ?
Or has the JAVA-ninja in you figured out a MW DataSeries Easter Egg ?
 
You use some kind of "external to MW" storage ?
Or has the JAVA-ninja in you figured out a MW DataSeries Easter Egg ?
Quite a lot to explain, but I can summarize it :)

Each of my studies are extending from a custom study class („MyStudy“), which in itself extends from Study - this gives me total monitoring possibilities and the centralized use and creation of helper methods and variables.

For storing informations across my studies I use a singleton class with a map where I can store any objects for each MyStudy-Object.

With my MyStudy Wrapper I added the possibility to execute the study with a given configurationMap without the need to add the study to my plot -> So I can have a master study that has multiple studies as dependencies and the master study will automatically calculate each dependency study in virtual threads and can then use the results (that each study is storing in the singleton map) for further calculations.
The dependency studies do not need to be on the plot, they can be calculated „remotely“ by passing the desired configuration/settings.
 
Now thát is some serious JAVA-MW-KungFu !!!
😆

Very 'hacky', but very well found ! Congrats @Dennis :)
I am sure you will get questions (per PM) on how to go about this in detail.
Many coders / traders are aiming for the same thing.
 
I will have some questions, but I will try to achieve it on my own first.
Thank you @Dennis for helping us to resolve this problem.
 
Top