Search code examples
user-interfaceplotslideroctavestochastic

How to code a slider in Octave to have interactive plot?


my target is to have a plot that shows Stochastic oscillator on forex market, and in order to validate which parameter is the best one to setup it, I would use a slider to modify it and show updated result on plot.

I have my historical data, for a defined pair (let say AUDUSD) and after loading it, I calculate Stocastic oscillator:

function [stoch, fk, dk] = stochastic(n, k, d)
    X=csvread("AUDUSD_2017.csv");
    C=X(2:length(X),5);
    L=X(2:length(X),4);
    H=X(2:length(X),3);
    O=X(2:length(X),2);
    for m=n:length(C)-n
        stoch(m)=((C(m)-min(L(m-n+1:m)))/(max(H(m-n+1:m))-min(L(m-n+1:m))))*100;

    endfor

for m=n:length(C)-n

    fk(m)=mean(stoch(m-d:m));

 endfor
for m=n:length(C)-n

    dk(m)=mean(fk(m-d:m));
endfor


endfunction

This is a picture of what I have when I plot stoch, fk and dk:

Plot based on parameters (14,7,7 as insput

I would add 3 sliders to the figure in order to change, in a range, parameters as input, so i.e. to have a slider that changes first parameter "n" between 3 and 50, "k" between 2 and 20, and "d" between 2 and 20.

I would use UI package in octave, can someone address me to have a plot updated when I use sliders?

Francesco


Solution

  • Andy pointed out in the comments that the example I linked to doesn't work on octave out of the box; this is because Octave doesn't like nested functions for certain things for the time being, so I've reproduced an 'octave version' below. Update (2023-03-31): nested functions have been supported for a while now: see update below old post for an example

    %%%%%% In file myplot.m %%%%%
    function myplot
    
      %% Create initial figure and spiral plot
      figure;  axes ('position', [0.1, 0.3, 0.8, 0.6]);
      global t;   t = linspace (0, 8*pi, 100);
      x = t .* cos(t);  y = t .* sin(t);
      plot (x, y);  axis ([-100, 100, -100, 100]);
    
      %% Add ui 'slider' element      
      hslider = uicontrol (                    ...
             'style', 'slider',                ...
             'Units', 'normalized',            ...
             'position', [0.1, 0.1, 0.8, 0.1], ...
             'min', 1,                         ...
             'max', 50,                        ...
             'value', 10,                      ...
             'callback', {@plotstuff}          ...
           );
    end
    
    %% Callback function called by slider event
    %% Also in file myplot.m (i.e. a subfunction)
    function plotstuff (h, event)
      global t;
      n = get (h, 'value');
      x = n * t .* cos(t);  y = n * t .* sin(t);
      plot (x, y);  axis ([-100, 100, -100, 100]);
    end
    

    enter image description here

    UPDATE (2023-03-31)

    Not sure at which point nested functions got properly supported, but at least as of octave 8.1 they are. Therefore the old example that used to be linked in the comments (but now points to a deleted matlab question) now works as intended. I am reproducing it here for future reference. Using a nested function instead of a subfunction is convenient, since this gives you access to the parent function's local variables, which removes the need for 'global variable' hacks, etc.

    %%%%%% In file myplot.m %%%%%
    function myplot
    
      %% Create initial figure and spiral plot
      figure;  axes ('position', [0.1, 0.3, 0.8, 0.6]);
      t = linspace (0, 8*pi, 100);  x = t .* cos(t);  y = t .* sin(t);
      plot (x, y);  axis ([-100, 100, -100, 100]);
    
      %% Add ui 'slider' element      
      hslider = uicontrol (                    ...
             'style', 'slider',                ...
             'Units', 'normalized',            ...
             'position', [0.1, 0.1, 0.8, 0.1], ...
             'min', 1,                         ...
             'max', 50,                        ...
             'value', 10,                      ...
             'callback', {@plotstuff}          ...
           );
    
      %% Callback function called by slider event
      function plotstuff (h, event)
        n = get (h, 'value');
        x = n * t .* cos(t);  y = n * t .* sin(t);
        plot (x, y);  axis ([-100, 100, -100, 100]);
      end
    end