Learning Freemat to analyse stock data

367 views
Skip to first unread message

TrendXplorer

unread,
Sep 5, 2013, 2:42:37 PM9/5/13
to fre...@googlegroups.com
First post from a new "user". Just starting to get a little bit acquainted with Freemat.

On my blog (www.trendxplorer.info) I publish free "thinkscript" studies: indicators and strategies for the TDA thinkorswim platform (www.thinkorswim.com).
After reading some posts on Seeking Alpha (see i.e. http://seekingalpha.com/instablog/709762-varan/2172362-a-strategy-for-trading-closed-end-funds) I wanted to learn a platform to create scripts for analysing and optimizing stock data, or at least to it a serious try.

Flabbergasted by the pricing of MatLab ("commercial user"), I found Freemat and this group too.

My first Freemat endeavour is:
- find readable stock data: .csv file form Yahoo Financial [tick]
- let Freemat read and order the data (adj. daily close, last column) [tick]
- plot a price chart [tick]
  (see attachment)
- plot a date defined x-axis [….]
- plot the price data on semi-log y-axis [….]
- plot a 200 day simple moving average on the price chart [….]
- calculate overall profit for long when price >= 200sma and short when price < 200sma (so the crossover of the 200sma triggers both exit and entry[….]
- plot a separate chart for profit's histogram (time, dollars) [….]
- code an optimization script to find max profit for long/short when above/below z day sma (i.e. calculate profits for each value of z between 10 and 300 with increments of 5) [….]
- generate/print an ordered (max to low) table with profits for every z value [….]

As I can imagine the coding of such a "scriptorium" would involve a lot of time and effort, I have no intention as to ask for anyone to write the code for me. I would however very much appreciate some guidance and hints during the process.

So, could anyone help me get going with the simple moving average?

TrendXplorer



spyscript.png

Timothy Cyders

unread,
Sep 5, 2013, 6:40:42 PM9/5/13
to fre...@googlegroups.com
A good way to do a moving average would be with convolution. I don't have time at the moment to explain the details, but here would be a coding example:

n = 10; % take moving average over 10 points
y= ones(1,n)/n; % weight points evenly as 1/n (you can change this to suit your needs - if you want to weight more recent data, for example, etc.)
x = [yourdatahere]; % row vector
movingaverageoutput = conv(x,y);

Note that the convolution will add data to each end of the matrix - depending on what you want to do, you can clip this however you like. Google around, and I'm sure you'll come across others using the technique. Hope this gets you started!

Cheers,
TJ


--
You received this message because you are subscribed to the Google Groups "freemat" group.
To unsubscribe from this group and stop receiving emails from it, send an email to freemat+u...@googlegroups.com.
To post to this group, send email to fre...@googlegroups.com.
Visit this group at http://groups.google.com/group/freemat.
For more options, visit https://groups.google.com/groups/opt_out.

TrendXplorer

unread,
Sep 6, 2013, 4:42:32 PM9/6/13
to fre...@googlegroups.com
This is really very helpful:
- sma [tick] :))

TJ, thanks!






sma_test.png
average.m
spy_1994_2012.csv
spy_average.m
spy_sma.png

TrendXplorer

unread,
Sep 7, 2013, 2:45:12 PM9/7/13
to fre...@googlegroups.com
Follow up after some long hours with "trail-and-error".
Some progress has been made, but alas no sigar.
Anybody for a match?

Thanks to the simple moving average code provided by TJ today I managed to write my first function: sma.m

% sma.m

%

% calculate simple moving average

% code courtesy of TJ

function return_value = sma(data,n) % moving average of "data" over "n" points

w = ones(1,n)/n; % weight points evenly as 1/n

return_value = conv(data,w);

% end


After plotting the difference between the daily closing price of SPY and the 200-day sma in points and next in %, eventually the script below evolved to calculate total performance over 11 years.
The rules are quite simple: when and during (close >= sma) we go/stay "long" otherwise "short".
Every day the daily difference (in %) is calculated and stored.
At the end of the price array, all differences are summed.
(NB! Not completely sure about the arithmetical validity of the calculations and summing, but for now that is the least of my problems).

Works OK for one specific sma length, like 200: the code yields a graphical equity curve and a report with: sma-length, profit% and number of trades. Great! (see attachments).
But as soon as I alter the starting value for the loop from 200 to i.e. 20, the script throws an error... Error: index is out of bounds
I suspect the error is caused by some improper use of the "report" array, not sure though?
Is "report" the culprit and how should I handle the storing of the daily "delta's"?

Another issue bugging me is a correct x-axis: the data window is from 2000-09-01 until 2011-08-31.
(: a period during which the "buy-and-hold" investor ended with about the same capital (actually a bit less) he started with at the left hand side of the chart (ex dividends))
The dates are available in the first column of the .csv, but how can they used for the x-axis?

Any help would be very much appreciated!

---------------------------------

% spy_sma_report.m

%

% calculate profit on trading SPY long/short when above/below x-length sma


% clear buffers

clear all;

close('all');


% read data from file

data = csvread('spy_2000_2011.csv',1,7); % column with adj. closes

close = flipdim(data,1); % order chronological: oldest first

lastrow = numel(close); % last row number of array


% report structure

% desired format: sma-length | profit% | #trades

%report(1,1) = ' sma-length ';

%report(1,2) = ' profit% ';

%report(1,3) = ' #trades ';

report = [0,0,0,0,0];


% optimization loop to find sma with highest performance

% set values for optimization loop:

startvalue = 200; % startvalue for sma-length <<<<<< 200: OK, 20: Error: index is out of bounds

endvalue = 200; % endvalue for sma-length

step = 10; % increase per iteration

rownumber = 1; % row number for report array


% initiate tradecounter

trend = 0; % long when 1, short when -1

% the crossover over the sma triggers a buy and a sell

trades = 1;


for (length = startvalue:step:endvalue);

% calculate "length" day simple moving average:

% calling function "sma.m"

sma = sma(close,length);


% loop through array, row by row

% calculate daily profit% for long cq short

% condition for long : close(n) >= sma(n)

% condition for short: close(n) < sma(n)

for (n = length:lastrow);

% long

if ( close(n) >= sma(n) );

delta(n) = (close(n) - close(n-1))/close(n-1);

if (trend < 1);

trend = 1;

trades = trades + 2;

end

% short

else

delta(n) = (-1) * (close(n) - close(n-1))/close(n-1);

if (trend > -1);

trend = -1;

trades = trades + 2;

end

end

end

% performance

total = floor( 100 * cumsum(delta) );

% store result to report array

report(rownumber,1) = length;

report(rownumber,3) = total(lastrow);

report(rownumber,5) = trades;

% raise rownumber

rownumber = rownumber + 1;

end


% plot equity curve

equity = (100 + total);

plot (equity);

grid on;


% output of result as report table

% desired format:

% sma-length | profit% | #trades

% sss ppp ttt

sma______pofit___trades = report


% end







sma_report.png
chart.png
perc_diff_200.png
spy_2000_2011.csv
sma.m
spy_sma_report.m

TrendXplorer

unread,
Sep 9, 2013, 4:24:22 PM9/9/13
to fre...@googlegroups.com
TIA,

Rearranging the code and the usage of a .csv-file brought the solution.
Loop is running like it should.
For each run the results are written to the .csv-file.
After finalizing the loop the contents of the .csv are loaded and printed on screen (no further alignment necessary).

I have some more questions, but they can wait until a later moment.

Please feel free to comment or make suggestions for improvement.

Thank you for your patience.
TrendXplorer

---------------------------------------------------------------------------

% report.m

%

% calculate profit on trading SPY long/short when above/below x-length sma


% clear buffers

clear all;

close('all');


% read data from file

data = csvread('spy_1999_2012.csv',1,7); % newest price on top of file

close = flipdim(data,1); % chronological order

lastBar = numel(close); % total number of bars


% use whole years for proper x-axis

startYear = 1998; % year before first trading day

endYear = 2012; % year with last trading day


% create report.csv to hold results

fp = fopen('report.csv','w');

fclose(fp);


% optimization loop to find sma with highest performance

% set values for optimization loop:

startvalue = 20; % startvalue for sma-length <<<<<< 200: OK, 20: Error: index is out of bounds

endvalue = 200; % endvalue for sma-length

step = 10; % increase per iteration

rownumber = 1; % row number for report array


for (length = startvalue:step:endvalue);


% initiate tradecounter

trend = 0; % long when 1, short when -1

% the crossover over the sma triggers a buy and a sell

trades = 1;


% calculate "length" day simple moving average:

% calling function "sma.m"

sma = sma(close,length);


% loop through array, row by row

% calculate daily profit% for long cq short

% condition for long : close(n) >= sma(n)

% condition for short: close(n) < sma(n)

for (n = length:lastBar);

% long

if ( close(n) >= sma(n) );

delta(n) = ( close(n) - close(n-1) ) / close(n-1);

if (trend < 1);

trend = 1;

trades = trades + 2;

end

% short

else

delta(n) = (-1) * ( close(n) - close(n-1) ) / close(n-1);

if (trend > -1);

trend = -1;

trades = trades + 2;

end

end

end

% performance

profit = floor( 100 * cumsum(delta) );

% equity

equity = 100 + profit(end);


% update report.csv

string = [num2str(length) ',' num2str( profit(end) ) ',' num2str(trades) '\n'];

fp = fopen('report.csv','a');

fprintf(fp,string);

fclose(fp);


% reset variables

clear sma trend trades delta profit equity;

end


report = csvread('report.csv')


%

% --- script end ---

%


report_screenshot.png
Reply all
Reply to author
Forward
0 new messages