Code covered by the BSD License  

Highlights from
Real-Time Stock Viewer

image thumbnail

Real-Time Stock Viewer

by

 

25 Aug 2004 (Updated )

Plot and analyze live market data from Bloomberg or Yahoo.

Editor's Notes:

This file was a File Exchange Pick of the Week

RTviewer(varargin)
function varargout = RTviewer(varargin)
% RTVIEWER GUI to monitor the prices of stocks using the Datafeed Toolbox
% 
% This demo shows how TIMER objects can be used to create a "real-time"
% trading appliction with MATLAB.
%
% Using the Datafeed Toolbox (Bloomberg or Yahoo) to import live market
% data or MATLAB's random number generation, this tool plots the data as it
% is imported or created, and displays whether the last price is higher or
% lower than the previous price.  If the price is higher, the point on the
% graph is plotted in green.  If it is lower, it is plotted as red.
% Otherwise it is plotted blue.
%
% This program could be used as a starting point to creating more detailed
% real-time trading applications.
%
% Author:
% Brian Kiernan
% Application Engineer
% The MathWorks, Inc.
% August 27, 2004

% Edit the above text to modify the response to help RTviewer

% Last Modified by GUIDE v2.5 19-Aug-2004 16:19:45

% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name',       mfilename, ...
                   'gui_Singleton',  gui_Singleton, ...
                   'gui_OpeningFcn', @RTviewer_OpeningFcn, ...
                   'gui_OutputFcn',  @RTviewer_OutputFcn, ...
                   'gui_LayoutFcn',  [] , ...
                   'gui_Callback',   []);
if nargin && ischar(varargin{1})
    gui_State.gui_Callback = str2func(varargin{1});
end

if nargout
    [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
    gui_mainfcn(gui_State, varargin{:});
end
% End initialization code - DO NOT EDIT


% --- Executes just before RTviewer is made visible.
function RTviewer_OpeningFcn(hObject, eventdata, handles, varargin)
% This function has no output args, see OutputFcn.
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
% varargin   command line arguments to RTviewer (see VARARGIN)

% Choose default command line output for RTviewer
handles.output = hObject;

% Get Ticker
ticker = upper(get(handles.edtTicker,'string'));

% Find today's date
clk = clock; 
todaydate = datenum(clk(1),clk(2),clk(3));
setappdata(gcf,'todaydate',todaydate)

% Create Empty Graph
circs = scatter([],[],'filled');
grid on
title(['Real Time Price Series of ',ticker,', ',datestr(todaydate)])
xlabel('Time')
ylabel('Price ($)')

% Define timer object based on Random Data as default
handles.t = timer('TimerFcn',{@randomRT, ticker},'ExecutionMode', ...
    'fixedRate');

handles.ticker = ticker;

% Pre-define price and time vectors for the data
setappdata(gcf,'bloomprice',[]);
setappdata(gcf,'bloomtime',[]);
setappdata(gcf,'yahooprice',[]);
setappdata(gcf,'yahootime',[]);
setappdata(gcf,'randomprice',[]);
setappdata(gcf,'randomtime',[]);
setappdata(gcf,'circs',circs)

guidata(hObject, handles);

% --- Outputs from this function are returned to the command line.
function varargout = RTviewer_OutputFcn(hObject, eventdata, handles) 
% varargout  cell array for returning output args (see VARARGOUT);
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Get default command line output from handles structure
varargout{1} = handles.output;


% --- Executes on button press in tglRun.
function tglRun_Callback(hObject, eventdata, handles)
% Start and stop collecting data

% Get booling start of stopping value of toggle button
stopgo = get(hObject,'Value');

% Get period and ticker
period = get(handles.sldPeriod,'value');
ticker = upper(get(handles.edtTicker,'string'));

% Find all timers
alltimers = timerfind;
% Start and stop the timer, but only if it exists
if ~isempty(alltimers) & isfield(handles,'t')
    % Start Viewing Data
    if stopgo
        set(handles.t,'Period',period)
        start(handles.t)
        set(hObject,'string','Stop')
        set(hObject,'BackGroundColor','r')
        set(handles.edtTicker,'enable','off')
    else
        stop(handles.t)
        set(hObject,'BackGroundColor','g')
        set(hObject,'string','Run')
        set(handles.edtTicker,'enable','on')
    end

else
        % Timer doesn't exist, this will force the user to 
    % create one using the other controls
    set(hObject,'string','Run','BackGroundColor','g', ...
        'value',0)
end

%update handles structure
guidata(hObject,handles)

% --- Executes on slider movement.
function sldPeriod_Callback(hObject, eventdata, handles)
% Change updating period via the slider control

% Fetch updating period from the slider
period = get(hObject,'Value');
handles.period = period;

% pass the period defined with the slider to the edit box
set(handles.edtPeriod,'string',num2str(period))

% If the timer is running, it needs to be turned off before
% updating the period
if isfield(handles,'t')
    if isequal(get(handles.t,'Running'),'on')
        % Stop timer
        stop(handles.t)
        
        % change period
        set(handles.t,'Period',period)
        
        % Start it back up
        start(handles.t)
    end
end

% update handles structure
guidata(hObject,handles)

% --- Executes during object creation, after setting all properties.
function sldPeriod_CreateFcn(hObject, eventdata, handles)
usewhitebg = 1;
if usewhitebg
    set(hObject,'BackgroundColor',[.9 .9 .9]);
else
    set(hObject,'BackgroundColor',get(0,'defaultUicontrolBackgroundColor'));
end


function edtPeriod_Callback(hObject, eventdata, handles)
% change the updating period via the edit control

% Fetch period value from the edit box
period = str2double(get(hObject,'String'));

% Set slider period value to period
set(handles.sldPeriod,'value',period)

% if the timer is running, it needs to be turned off before
% updating the period
if isfield(handles,'t')
    if isequal(get(handles.t,'Running'),'on')
        % Stop timer
        stop(handles.t)
        
        % change period
        set(handles.t,'Period',period)
        
        % Start it back up
        start(handles.t)
    end
end

handles.period = period;
guidata(hObject,handles)

% --- Executes during object creation, after setting all properties.
function edtPeriod_CreateFcn(hObject, eventdata, handles)
if ispc
    set(hObject,'BackgroundColor','white');
else
    set(hObject,'BackgroundColor',get(0,'defaultUicontrolBackgroundColor'));
end


function edtTicker_Callback(hObject, eventdata, handles)

% Delete timer objects
handles = timerconncleanup(handles);

% Clear Plot and Reset Values
dataplotreset(handles.ticker)

% Fetch Parameters
period = get(handles.sldPeriod,'value');
ticker = upper(get(hObject,'string'));

% Find which data source has been selected
btngrpchil = get(handles.btngrpData,'children');
btngprchil = findobj(btngrpchil,'style','radio');
vals = get(btngrpchil,'value');
datasource = find(cell2mat(get(btngrpchil,'value')));

if datasource == 3;  % Bloomberg
    ticker = [ticker,' US Equity'];
    
    % Create and test for valid Bloomberg connection
    try
        handles.Conn = bloomberg;
    catch
        err = errordlg('Invalid Bloomberg Connection');
        set(err,'windowstyle','modal')
        return
    end
    
    % Test if the ticker is valid
    try
        dummy = fetch(handles.Conn,ticker,'GETDATA','Last_Price');
    catch
        err = errordlg('Data fetch failed. Possible invalid ticker.', ...
            'Bloomberg Error','on');
        set(err,'WindowStyle','modal')
        close(handles.Conn)
    return
    end

    % Update Timer Object to use Bloomberg and use new ticker
    handles.t = createtimer(@bloomRT,ticker,period,handles,handles.Conn);
    
elseif datasource == 2
    
    % Create and check for valid Yahoo connection
    try
        handles.Conn = yahoo;
    catch
        err = errordlg('Invalid Yahoo Connection');
        set(err,'windowstyle','modal')
        return
    end
    
    % Test if the ticker is valid
    try
        dummy = fetch(handles.Conn,ticker,'Last');
    catch
        err = errordlg('Data fetch failed. Possible invalid ticker.', ...
            'Yahoo Error','on');
        set(err,'WindowStyle','modal')
        close(handles.Conn)
        return
    end
    
    % update Timer to use Yahoo with new Ticker
    handles.t = createtimer(@yahooRT,ticker,period,handles,handles.Conn);

else
    
    % Update Timer Object with new ticker for the plot
    handles.t = createtimer(@randomRT,ticker,period,handles);
    
end

% Update handles structure
guidata(hObject,handles)


% --- Executes during object creation, after setting all properties.
function edtTicker_CreateFcn(hObject, eventdata, handles)
if ispc
    set(hObject,'BackgroundColor','white');
else
    set(hObject,'BackgroundColor',get(0,'defaultUicontrolBackgroundColor'));
end

% --- Executes on button press in radRandom.
function radRandom_Callback(hObject, eventdata, handles)
% Random Radio Button Callback.
% define timer to use random data

% Turn off existing timer object and delete it
handles = timerconncleanup(handles);

% Clear Plot and Reset Values
dataplotreset(handles.ticker)

% Fetch Parameters
period = get(handles.sldPeriod,'value');
ticker = upper(get(handles.edtTicker,'string'));

handles.t = createtimer(@randomRT,ticker,period,handles);

guidata(hObject,handles)


% --- Executes on button press in radYahoo.
function radYahoo_Callback(hObject, eventdata, handles)
% Yahoo Radio Button Callback.
% Define Timer to use Yahoo data source

% Turn off existing timer object and delete it
handles = timerconncleanup(handles);

% Clear Plot and Reset Values
dataplotreset(handles.ticker)

% Fetch Parameters
period = get(handles.sldPeriod,'value');
ticker = upper(get(handles.edtTicker,'string'));

% Create and check for valid Yahoo connection
try
    handles.Conn = yahoo;
catch
    err = errordlg('Invalid Yahoo Connection');
    set(err,'windowstyle','modal')
    return
end

% Test if the ticker is valid
try
    dummy = fetch(handles.Conn,ticker,'Last');
catch
    err = errordlg('Data fetch failed. Possible invalid ticker.', ...
        'Yahoo Error','on');
    set(err,'WindowStyle','modal')
    close(handles.Conn)
    return
end
    
handles.t = createtimer(@yahooRT,ticker,period,handles,handles.Conn);

guidata(hObject,handles)


% --- Executes on button press in radBloomberg.
function radBloomberg_Callback(hObject, eventdata, handles)
% Bloomberg Radio Button Callback.
% Defind timer to use Bloomberg for a data source

% Turn off existing timer object and delete it
handles = timerconncleanup(handles);

% Clear Plot and Reset Values
dataplotreset(handles.ticker)

% Fetch Parameters
period = get(handles.sldPeriod,'value');
ticker = upper(get(handles.edtTicker,'string'));
ticker = [ticker,' US Equity'];
% Create and test for valid Bloomberg connection
try
    handles.Conn = bloomberg;
catch
    err = errordlg('Invalid Bloomberg Connection');
    set(err,'windowstyle','modal')
    return
end

% Test if the ticker is valid
try
    dummy = fetch(handles.Conn,ticker,'GETDATA','Last_Price');
catch
    err = errordlg('Data fetch failed. Possible invalid ticker.', ...
        'Bloomberg Error','on');
    set(err,'WindowStyle','modal')
    close(handles.Conn)
    return
end
    
% Create New Timer with new TimerFcn, period, and ticker    
handles.t = createtimer(@bloomRT,ticker,period,handles,handles.Conn);
guidata(hObject,handles)

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function randomRT(obj,event,ticker)
% Random Real-Time processing function

% Create Random Price
LastPrice.Last = 100*rand;
TickTime = datenum(event.Data.time);

% Update Price and Time vectors for plotting
Pricevector = [getappdata(gcf,'randomprice'); LastPrice.Last];
setappdata(gcf,'randomprice',Pricevector)
Timevector = [getappdata(gcf,'randomtime'); TickTime];
setappdata(gcf,'randomtime',Timevector)

% Plot the New Data
plotRT(ticker,Pricevector,Timevector)

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function yahooRT(obj,event,Conn,ticker)
% Yahoo Real-Time processing function

% Fetch price data from Yahoo
LastPrice = fetch(Conn,ticker,'Last');
TickTime = datenum(event.Data.time);

% Update Price and Time vectors for plotting
Pricevector = [getappdata(gcf,'yahooprice'); LastPrice.Last];
setappdata(gcf,'yahooprice',Pricevector)
Timevector = [getappdata(gcf,'yahootime'); TickTime];
setappdata(gcf,'yahootime',Timevector)

% Plot the New Data
plotRT(ticker,Pricevector,Timevector)


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function bloomRT(obj,event,Conn,ticker)
% Bloomberg Real-Time processing function

% Fetch Price from Bloomberg
LastPrice = fetch(Conn,ticker,'GETDATA','Last_Price');
TickTime = datenum(event.Data.time);

% Update Price and Time vectors for plotting
Pricevector = [getappdata(gcf,'bloomprice'); LastPrice.Last_Price];
setappdata(gcf,'bloomprice',Pricevector)
Timevector = [getappdata(gcf,'bloomtime'); TickTime];
setappdata(gcf,'bloomtime',Timevector)

% Plot the New Data
plotRT(ticker,Pricevector,Timevector)

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function plotRT(ticker,Pricevector,Timevector)
% General Plotting function for real-time data

% Get handle to the status text box
statusbox = findobj(gcf,'style','text','tag','txtStatus');
circs = getappdata(gcf,'circs');

if length(Pricevector) == 1

    % Plot first Price
    set(circs,'xdata',Timevector,'ydata',Pricevector,'cdata',[0 0 1]);
    setappdata(gcf,'circs',circs);
    axispos = axis;
    set(gca,'xtick',Timevector,'xticklabel',datestr(Timevector,13))

else
    % Test for up or down movement and lable graph points accordingly
    if Pricevector(end) > Pricevector(end-1)
        % update status text box
        set(statusbox,'string','price is higher')
        % Create a green RGB color for the point on the graph
        dotcolor = [0 1 0];
    elseif Pricevector(end) < Pricevector(end-1)
        % update status text box
        set(statusbox,'string','price is lower')
        % Create a red RGB color for this point on the graph
        dotcolor = [1 0 0];
    else
        % update status text box
        set(statusbox,'string','price is unchanged')
        % Create a blue RGB color for this point on the graph
        dotcolor = [0 0 1];
    end
    
    % Fetch current x(time) and y(price) data from the graph
    ctime = get(circs,'xdata');
    cprice = get(circs,'ydata');
    
    % Fetch current colormapping, and update it with the color
    % of the next dot, which was defined above.
    colormat = get(circs,'Cdata');
    colormat = [colormat;dotcolor];
    
    % Update scatter plot with new price point
    set(circs,'xdata',[ctime,Timevector(end)], ...
        'ydata',[cprice, Pricevector(end)],'Cdata',colormat)
    
    % Find and delete line plot so as not to plot too many lines
    dummyline = findobj(gca,'type','line');
    if ~isempty(dummyline)
        delete(dummyline)
    end
    
    % Plot Connecting Line
    plot(Timevector,Pricevector)
    
    % 5 percent of the data range
    x5per = .05*(max(Timevector) - min(Timevector));
    
    % Calculate the lowest and hightest price so far
    lowprice = min(Pricevector);
    highprice = max(Pricevector);
    Range = highprice - lowprice;
    %update axes size for better viewing
    if Range == 0
        axispos = axis;
    else
        axispos = [Timevector(1)-x5per,Timevector(end)+x5per, ...
        max(0,lowprice-Range*.05),highprice+Range*.05];
    end
    
    if length(Timevector) > 2
        % Create appropriate axis viewing range
        axis(axispos)
        datetick('x',13)
    end
end

% Add Title and grid to graph
title(['Real Time Price Series for ', ticker,', ',datestr(Timevector(1),1)])
ylabel('Price (USD)')
grid on
hold on

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% --- Executes when user attempts to close figure1.
function figure1_CloseRequestFcn(hObject, eventdata, handles)
% hObject    handle to figure1 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

handles = timerconncleanup(handles);

delete(hObject);


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function handles = timerconncleanup(handles)

alltimers = timerfind;

if ~isempty(alltimers) & isfield(handles,'t')
    if isequal(get(handles.t,'Running'),'on')
        stop(handles.t)
    end
    % use TIMERFIND function to find all timers, and delete them
    delete(alltimers)
    rmfield(handles,'t');
elseif isfield(handles,'t')
    rmfield(handles,'t');
end

if isfield(handles,'Conn')
    close(handles.Conn)
end

set(handles.tglRun,'value',0,'backgroundcolor','g','string','Run')
% guidata(handles.figure1,handles)


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function dataplotreset(ticker)

% Get Today's date
todaydate = getappdata(gcf,'todaydate');

reset(gca)
% Create Empty Graph
circs = scatter([],[],'filled');
grid on
title(['Real Time Price Series of ',ticker,', ',datestr(todaydate)])
xlabel('Time')
ylabel('Price ($)')
setappdata(gcf,'circs',circs)

% Data Reset
setappdata(gcf,'bloomprice',[]);
setappdata(gcf,'bloomtime',[]);
setappdata(gcf,'yahooprice',[]);
setappdata(gcf,'yahootime',[]);
setappdata(gcf,'randomprice',[]);
setappdata(gcf,'randomtime',[]);


function tim = createtimer(realtimefun,ticker,period,handles,Conn)
% Create timer object with the datasource defined by the realtimefun
% function handle, and with ticker symbol and update period defined buy
% ticker and period respectiveley.

if nargin == 4
    tim = timer('TimerFcn',{realtimefun, ticker},'ExecutionMode', ...
    'fixedRate', 'Period', period);
else
    % Create timer object with the Yahoo or Bloomberg data source TimerFcn
    tim = timer('TimerFcn',{realtimefun, Conn, ticker},'ExecutionMode', ...
    'fixedRate', 'Period', period);
end

Contact us