Can you help me with the following issue?
I have a large dataset of intraday financial data. More specifically, closing stock prices of each 15 minutes for multiple days. I face a problem in plotting the timeseries of the data.
Here is an example of my series:
'29-Dec-2016 15:00:00' 62.8400000000000
'29-Dec-2016 15:15:00' 62.8300000000000
'29-Dec-2016 15:30:00' 62.8900000000000
'29-Dec-2016 15:45:00' 62.8550000000000
'29-Dec-2016 16:00:00' 62.8900000000000 (Closing of the market)
'30-Dec-2016 09:45:00' 62.7300000000000 (Opening of the market)
'30-Dec-2016 10:00:00' 62.2900000000000
'30-Dec-2016 10:15:00' 62.2400000000000
'30-Dec-2016 10:30:00' 62.0900000000000
'30-Dec-2016 10:45:00' 62.1100000000000
'30-Dec-2016 11:00:00' 62.3000000000000
'30-Dec-2016 11:15:00' 62.2300000000000
If I plot the above subsample the matlab plot will have a form like the following picture:
As you can see the Matlab plotting fills in the horizontal axis with the time between the closing of the market and the opening of the market which makes the price to look "stretched".
Contrary if i use an increasing observation number (e.g. 1 to 100...) the problem is removed like in the following picture:
Is there a way to avoid the "stretch" of the price and still have time on my horizontal axis?
Thanks in advance.
You can do this way:
First plot only price data
plot(price)
Then set the XTickLabel:
set(gca,'XTickLabel',datevector)
This will set the X axes with your data
You can put this inside a function
function plotprices(data)
datevector = data(:,1); %store dates in first column
price = num2cell(data(:,2)); %store prices in second column
plot(price)
set(gca,'XTickLabel',datevector)
You can read the positions of the x-ticks on the plot and replace their labels with your own strings. So, assuming:
a) y has the stock prices, and
b) Date has the date strings,
you could add the following code at the end of the second plot to get something close to what you want:
% limit the x-axis such that all ticks are within the data range
xlim([1, length(y)]);
% read the marks of the x-ticks
xt=get(gca, 'XTick');
% this would place the x tick marks at the same locations
% that Matlab chose by default. If you want to place them
% at some other points, just assign those points to xt, e.g.
% xt = (1:10:length(y))
% replace the labels of the marks
set(gca, 'XTick', xt); % rewrite this in case you modify xt
set(gca,'XTickLabel',Date(xt))
BTW, a potentially simpler alternative is to use your first plot but instead of solid line, use markers only. For example, plot(Date, y, '.');
Related
I have below these three vectors:
CoverageArea_mean = [84.4735,0,21.1779,4.5211,6.4247,2.3795,2.1416,0]; %FEC = 3.8x10^-3
CoverageArea_min = [98.5128,92.5640,21.1779,21.1779,6.9007,6.9007,2.1416,2.1416]; %FEC = 3.8x10^-3
CoverageArea_max = [70.1963,0,19.0363,0.4759,5.9488,0.2380,2.1416,0]; %FEC = 3.8x10^-3
I would like to draw them as in the figure below:
x = [15 15 30 30 45 45 60 60];
I am not sure If they will be fit for the box plot or not. I want to take a value from the three vectors every time and represent them as a above.
Any idea or assistance, please?
1.- I call marker (as in oscilloscopes) what in MATLAB is called pointer.
2.- I have modified Davidson's function plot_candlesticks available here
https://uk.mathworks.com/matlabcentral/fileexchange/9893-candlesticks?s_tid=srchtitle_financial%20charts_23
Mathworks File exchange name: candlesticks version 1.0.0.0 (1.44 KB) by Bill Davidson
Bill grants permission for modifications.
3.- With the following functions and test script you can generate graphs like this
The addition of text labels is a really easy task that I have started, as you can see in the test script, but ran out of time for this question so I let you finish it off, let me know if you encounter any problem.
I recommend you use command text outside the supplied functions, after plotting the graph
4.- I give you 2 functions: plot_tees and plot_bars . The function you asked for is plot_tees
function [hpt]=plot_tees(ax1,x,highs,lows,opens,closes,sh,col_stick)
% plot_tees plots T and inverted T on supplied data points
% input checks: PENDING
% make sure x has no gaps and same interval
% make sure all input lengths are the same : x highs lows opens closes
% check amount inputs and expected formats ok
middle=sh.middle
hwbody=sh.hwbody
hwshad=sh.hwshad
xbody=sh.xbody
xshad=sh.xshad
npoints=length(highs);
hpt=[0 0 0];
for k1=1:npoints
hp1(k1,1)=plot(ax1,[.5+x(k1)-.2 .5+x(k1)+.2],[highs(k1) highs(k1)],'Color',col_stick,'LineWidth',1.1); % top --
hp1(k1,2)=plot(ax1,[.5+x(k1)-.2 .5+x(k1)+.2],[lows(k1) lows(k1)],'Color',col_stick,'LineWidth',1.1); % low --
hp1(k1,3)=plot(ax1,[.5+x(k1) .5+x(k1)],[lows(k1) highs(k1)],'Color',col_stick,'LineWidth',1.1); % the actual stick
hpt=[hpt; hp1];
end
hpt(1,:)=[];
end
and plot_bars
function [hpt]=plot_bars(ax1,x,highs,lows,opens,closes,col_down,sh,col_up)
% plot_bar plots high-low bars on supplied data
% input checks
% make sure x has no gaps and same interval
% make sure all lengths are the same :x highs lows opens closes
middle=sh.middle
hwbody=sh.hwbody
hwshad=sh.hwshad
xbody=sh.xbody
xshad=sh.xshad
npoints=length(x);
colors=closes<opens;
colors=char(colors*col_down+(1-colors)*col_up); % 'k' black 'w' white 'r' red 'b' blue or custom RGB [r g b] range [0 1]
% h1=figure(1)
hpt=[];
for k1=1:npoints
hp1=patch(ax1,x(k1)+xbody,[opens(k1),opens(k1),closes(k1),closes(k1),opens(k1)],colors(k1));
hpt=[hpt hp1];
end
end
This is the TEST SCRIPT HERE :
close all;clear all;clc
% opns : opens clos : closes , avoiding var names too close to reserved names
col_down='r'
col_up='r'
col_stick='k'
% this is to avoid having to make changes inside each function
sh.middle=0.5;
sh.hwbody=sh.middle/2;
sh.hwshad=sh.hwbody/10;
sh.xbody=sh.middle+[-sh.hwbody sh.hwbody sh.hwbody -sh.hwbody -sh.hwbody];
sh.xshad=sh.middle+[-sh.hwshad sh.hwshad sh.hwshad -sh.hwshad -sh.hwshad];
% time reference
npoints=15 % amount CONSECUTIVE days
x=[1:npoints] % day points
% data
y_mean0=50 % DC to avoid graph 002
y=rand(npoints,1)-0.5
opns=y_mean0+cumsum(y)
highs=opns+rand(npoints,1)
lows=opns-rand(npoints,1)
clos=opns+(highs-lows).*(rand(npoints,1)-0.5)
% plot frame
h1=figure(1)
ax1=gca
plot(ax1,[x(1)-1 x(end)+1],[y_mean0 y_mean0])
hold(ax1,'on')
plot(ax1,x,zeros(1,numel(x))+y_mean0,'|','Color',[.7 .7 .7]) % days reference
% plot data spans
hp1=plot_tees(ax1,x,highs,lows,opns,clos,sh,col_stick);
hold on
grid on; % off | minor
hp2=plot_bars(ax1,x,highs,lows,opns,clos,col_down,sh,col_up);
% include text tags
prec=7 % precision : amount total digits into string '.' not a digit
str_highs=num2str(highs,prec);
str_lows=num2str(lows,prec);
tr1=2 % trim, in case needed : how many decimal digits to drop from right hand side
str_highs(:,[end-tr1+1:end])=[];
str_lows(:,[end-tr1+1:end])=[];
% PENDING
% figure properties
h1.Name='graph 01';
h1.NumberTitle='off';
h1.ToolBar='auto'; % none | figure
h1.MenuBar='figure'; % | figure
h1.Color=[.7 .7 .7]; % figure background colour
ax1.Color=[.9 .9 .9]
% T-marker properties : modify T-marker properties here
for k1=1:1:size(hp1,1)
for k2=1:1:size(hp1,2)
hp1(k1,k2).LineWidth=1.1;
hp1(k1,k2).Color=[.9 .5 .3];
end
end
% bars properties : modify bar properties here
for k1=1:1:size(hp2,2)
hp2(k1).EdgeColor='none';
end
% plot aditional graphs
plot(ax1,x+.5,opns,'c','LineWidth',1.5)
5.- I am not using the data you supplied in the question. Instead I use randomly generated points.
You should have no trouble in replacing the random data with your data.
Let me know if any handicap.
5.1.- The time reference you supplied doesn't seem to match the supplied values; x has doubled values and there are more values than days
5.2.- The mean value hardly ever is exactly the average between each high and each low
5.3.- Using the data I know I could show how to do things like changing properties and including additional graphs, because with a clear time reference is available.
6.- Because you may need to change colours, bars opacity, bars edge, bars presence, and thickness of any, as well as there may be need to turn on/off each text field on graph (of each point and of all points) all handles to properties are now available.
Additional Comments :
7.- MATLAB built-in colours handy here
And some other commonly used custom colours
Any colour is available, just specify the RGB as vector [1 1 1] range of each element [0 1] 0: black, 1: white.
8.- MATLAB built-in markers are : arrow (default) ibeam crosshair watch topl botr circle cross fleur left right top bottom and hand.
One can also create custom pointers setting up figure property PointerShapeCData.
But none of these pointers are useful here because they are all 16x16 only, size matters.
This is why I asked in first place if the Ts had to be same size, or more reasonably, like in financial/investment/banking graphs you asked for T-markers proportional to the specified span, for each point.
9.- This question-answer has nothing to do with what is commonly known as T-graphs : 2 lists side by side to compare features.
10.- use uifigure instead of figure if you are building your app with App Builder.
I want to plot a time series (pricing data for a forex future contract). Time is given in yyyymmdd HH:MM:SS string format. Price is in double.
The time series spans over a week. However, the timestamp for the data points are always on weekdays. Is there a built-in method to display the appropriate x-axis labels and scaling but without weekends?
I can currently display the time series by converting the timestamp in string to datenum and arrange x-axis automatically with datetick. But I would like to know how to exclude weekends on the x-axis. Or exclude any extended interval of time from the grid where there is no data.
For a visual, please see example at the end. If one can exclude the large empty space due to including the weekend (Apr 10 was a US holiday), the plot can become more legible by focusing on where there is actually data.
The data points themselves are exclusive to weekdays. But between plot and datetick, grid points on weekends are created whenever the time series spans over a week. datetick is helpful because it detects the appropriate scaling for x-axis grid and applies the corresponding grid labels all in one go. If you see datetick as a part of the solution, is there a way to remove particular grid points after using datetick?
Example:
T=[7.378903958333334e+05;7.378967076388889e+05]; % converted from "20200409 09:30:00" and "20200415 16:59:00"
C=[0.7166;0.7090];
grid on
plot(T,C,'.')
xlim([min(T),max(T)])
datetick
If you are interested in tinkering with the same plot, please retrieve the data by c&p into Matlab cmd from pastebin. The same lines above will produce the following plot.
There is no such features. Probably, because this essentially makes the x-axis discontinuous, which is (usually) not desirable.
You will have to create a synthetic x-axis to achieve this by sorting out the the weekends (or rather the not business days).
This is the standard plot (the business days are blue)
% create data
T = 7.3789e+05+(0:5:100)/10.';
C = rand(size(T));
% is a busniess day?
lg = isbusday(T);
% standard date plot
plot(T(lg),C(lg),'o', T(~lg),C(~lg),'o')
datetick('x','ddd')
Now let us get rid of the other days and set the xTickLabel manually:
T = T(lg);
C = C(lg);
% plot without time-axis
plot(C,'o')
% --- get ticks
xTick = get(gca,'XTick');
% get which ticks are integers
lg = isreal(xTick) & rem(xTick,1)==0;
XTick_new = xTick(lg);
% --- create new tick label
xTickLbl_new_num = NaN(size(XTick_new));
% make sure they are within the limits
lg = XTick_new >= 1 & XTick_new <= length(T);
xTickLbl_new_num(lg) = T(XTick_new(lg));
% convert to string (arbitrary format)
xTickLbl_new_str = strings(size(xTickLbl_new_num));
xTickLbl_new_str(lg) = datestr(xTickLbl_new_num(lg),'ddd');
% set new label
set(gca,'XTick',XTick_new,'XTickLabel',xTickLbl_new_str);
Have a look on the results: left the standard version and on the right the version with manually set tick-labels.
I am currently trying to make 'nice looking' axis on my plot in Matlab. The values are samples where each is taken every 20ms. So on X axis I'd like to have time in ms. My general code for plotting data is very simple:
plot(1:size( data.matrix,1), data.matrix(:,1),'b');
So far I've been able to correctly display sample numbers on this axis:
Code:
set(gca,'XTick',(1:size(data.matrix,1))*20);
Result (a):
In the given example the number of samples equals 184, that makes:
time = 184 * 20ms = 3680ms
Because changing the XTick value didn't do much of a change, I've tested XTickLabel property:
Code:
set(gca,'XTickLabel',ceil(linspace(0,size(data.matrix,1)*20,10)));
Result (b):
Code:
set(gca,'XTickLabel',0:ceil((size(data.matrix,1)*20)/10):size(data.matrix,1)*20);
Result (c):
As you may see, the results aren't the worst one. But this is not what I am trying to achieve. My goal is to have values like this:
So it simply first plot's (result a) X axis multiplied by 20.
Can someone please tell me how to achieve this?
when you use :
plot(1:size( data.matrix,1), data.matrix(:,1),'b');
The first parameter 1:size( data.matrix,1) create a vector of consecutive integers representing the indices of your data points. Two things are wrong with that:
1) You do not need to specify it. Matlab plot function called with only the Y data will create this vector automatically and use it to plot the data.
2) These indices represent the position of your data in an array, they have no physical meaning (like "time" for your case).
The solution is to create a proper 'time' vector and send it as the first parameter to the plot function. This way Matlab will take care of the tick management and you don't have to temper with the manual xtick settings.
Look at the two ways of doing it in the example below and everything will be clear:
%// build a simple index "X" vector (as you were doing)
x_index = 1:size(data.matrix,1) ;
%// build a properly scaled time vector
timeInterval = 20 ; % in milliseconds
x_time = ( 0:size(data.matrix,1)-1 ) * timeInterval ;
plot( x_index , data.matrix(:,1) ) %// this will do like in your example
plot( x_time , data.matrix(:,1) ) %// this will do what you want
Can you not just do?
set(gca,'XTickLabel',(1:size(data.matrix,1))*20*20);
I'm currently having some trouble with the 'smooth' command, namely that it seems to have no effect on the generated plot. I have already used the following script to generate a plot
for h=1:4
linespec = {'rx', 'gx', 'bx', 'yx'};
hold on
for b=1:365
y=mean(mean(A(b,6*(h-1)+1:6*h)));
p(h)=plot(b,y,linespec{h});
end
hold off
end
Going row by row in data set A and taking the average of the values in the first six columns, then column 7 through 12, 13 through 18 and 19 through 14; generating four plots in total.
The next step was to smooth the resultant plot by averaging the values over a span of 9. So, I tweaked the script to the following;
for h=1:4
linespec = {'rx', 'gx', 'bx', 'yx'};
hold on
for b=1:365
y=mean(mean(A(b,6*(h-1)+1:6*h)));
w = smooth(y,9,'moving');
p(h)=plot(b,w,linespec{h});
end
hold off
end
Essentially just adding the w variable and replacing y with w in the plot command. Yet this has no effect whatsoever on my plot. Matlab doesn't throw up any errors either, so there doesn't seem to be a problem with the input size. Does anyone have an idea as to what the issue might be?
In either version of the loop, you appear to be plotting individual values of y against individual values of b. I presume, then, that y is a single value. You can't smooth a point, so the smooth operation is having no effect.
From the start, you don't need to make a loop to calculate the various means; mean can take a 2D matrix and return a vector. Calculate y in one go, then smooth that vector (should have length 365, I presume - depends on the size of input A). e.g.:
b = 1:365;
y=mean(A(:,6*(h-1)+1:6*h),2);
w = smooth(y,9,'moving');
plot(b,y,'rx');
hold on
plot(b,w,'gx');
I have data like this:
22.10.1980. 100
25.10.1980. 120
26.10.1980. 12
(only much more of it, and for each date, several independent measurements on the right).
Now, this is probably trivial, but I've never done anything like it in MATLAB, and am having problems finding similar examples online. I need to plot the data on a time/showing dates axis (x axis), with all dates inside (so, 23. and 24. as well ... for which I don't have measurements).
How can I get dates to show up on a plot axis?
It seems like it might be the best to use datetick.
Usage: datetick('x') or datetick('x', dateformat) with the available formats as explained in the documentation.
Assuming your data file has the format given above, you could use textscan to read the data:
fid = fopen('data.txt','rt');
C = textscan(fid,'%s %s %s %d','Delimiter','.','CollectOutput',1);
fclose(fid);
The first cell of C will contain an N-by-3 cell array of strings (the parts of the date) and the second cell of C will contain an N-by-1 vector of the data measurements. You can create a date number for each measurement by first concatenating the 3 smaller strings into one date string and then using the datenum function:
t = datenum(strcat(C{1}(:,3),'-',C{1}(:,2),'-',C{1}(:,1)));
data = C{2};
Once you have a vector of date numbers t to go with your vector of measurements data, you can then plot them:
plot(t,data,'*'); %# Plot the points as asterisks
Now, you can change the x-axis labels to show the actual dates. One option is to use the function datetick, an easy and elegant solution given in steven's answer. Another option is to use the function datestr to create the labels yourself, then modify the XTick and XTickLabel properties of the current axes:
xpts = min(t):max(t); %# Make a full vector, filling in missing dates
set(gca,'XTick',xpts,'XTickLabel',datestr(xpts)); %# Set axes properties
NOTE: Whichever option you choose for changing the x-axis labels to date strings, you may run into trouble with the labels overlapping each other if the tick marks are too close together. You could fix this by reducing or repositioning the tick marks along the x-axis (by changing the XTick property) or by adjusting the axes FontSize property. If you wanted to rotate the labels to make them fit, you would have to erase the labels and create new rotated text objects for them. The following submission on The MathWorks File Exchange does just that:
Rotate Tick Label by Andrew Bliss
With datenum you can convert any string date into numerical format based on the date format symbols (see help datestr).
For example all this leads to the same numerical date representation:
datenum('15/05/2009 21:22','dd/mm/yyyy HH:MM');
datenum('15.05.2009 21:22','dd.mm.yyyy HH:MM');
datenum('21-22 15.05.2009','HH-MM dd.mm.yyyy');
datenum('21-22 05/15.2009','HH-MM mm/dd.yyyy');
...
The nice thing is that you can pass cell array (output from textscan) or char array directly to datenum and it will output numeric date array.
Datetick is a good option, as well as datetick2, which can be found here: MATLAB Central
Datetick2 allows panning and zooming, with adjustments to the time labels, depending on how far you're zoomed in.
I'm not sure about the dd.mm.yyyy format - you could use regexp or strrep to change the decimals to dashes if neccessary.
You can use datenum to convert the dates to a numbers, and plot the data as usual. lets say you put your dates vector in the variable called x.
Now, you can use
set(gca, 'xtick',x(1:10:end));
set(gca, 'xticklabel',datestr(x(1:10:end));
to set the ticks on the x axis.