function tradebot
% TRADEBOT A naive automated trader
% Example : tradebot
global fileNames ...
fileFormats ...
colors ...
universeList ...
universeSize ...
portValue ...
epochsTrain ...
epochTimer ...
epochCount
fileNames = {'universelist.txt', ...
'universeprices.txt', ...
'universereturns.txt', ...
'portfolioreturns.txt', ...
'traderecords.txt'};
fileFormats = {'%d', ...
'%d\t%d\t%f', ...
'%d\t%d\t%f', ...
'%d\t%f\t%f\t%f', ...
'%d\t%d\t%f'};
colors = {[.8 .8 .8], ... % gray
[.6 .2 .3], ... % red
[.2 .6 .3]}; % green
[universeList] = textread(fileNames{1},fileFormats{1}); % arbitrary numeric ids
universeSize = length(universeList);
portValue = 100;
epochsTrain = 3;
epochsTrade = 30;
epochLength = 2;
epochCount = 0;
epochTimer = timer('StartDelay',0, ...
'Period',epochLength, ...
'TasksToExecute',epochsTrain + epochsTrade, ...
'ExecutionMode','fixedRate', ...
'TimerFcn',@completeEpoch, ...
'StopFcn', @abortStrategy);
createGUI
end
function createGUI
global hList ...
hPlot ...
hCash ...
hTime ...
hStop ...
portValue ...
colors
f = figure('Name','Tradebot: (Not Quite) Ready For Wall Street', ...
'Position',[3 500 400 270], ...
'NumberTitle','off', ...
'Color','w', ...
'Resize','off', ...
'MenuBar','none');
x = [.40 .68];
y = [.05 .15];
w = .25;
v = .10;
hStrt = guicontrol('pushbutton',f,[x(1) y(1) w v],'Start');
hStop = guicontrol('pushbutton',f,[x(2) y(1) w v],'Stop');
hTime = guicontrol('text' ,f,[x(1) y(2) w v],'Epoch: 0');
hCash = guicontrol('text' ,f,[x(2) y(2) w v],sprintf('Value: %.2f',portValue));
hList = addPortfolioListPanel; %#ok
hPlot = addPortfolioReturnPanel; %#ok
set(hStrt,'Callback',@startStrategy)
set(hStop,'Callback',@abortStrategy)
function[h] = addPortfolioListPanel
h = nan(10,2);
w = [.13 .13];
x = [.03 .17];
v = .066;
for i = 1:12
y = .90 - (i-1)*(v + .01);
if i == 1
set(guicontrol('text',f,[x(1) y .27 v],'Current portfolio'),'Fontweight','bold')
elseif i == 2
set(guicontrol('text',f,[x(1) y w(1) v],'ID' ),'BackgroundColor',colors{1})
set(guicontrol('text',f,[x(2) y w(2) v],'Weight'),'BackgroundColor',colors{1})
else
h(i-2,:) = [guicontrol('text',f,[x(1) y - 0.01 w(1) v],'') ...
guicontrol('text',f,[x(2) y w(2) v],'')];
end
end
end
function[h] = addPortfolioReturnPanel
x = .40;
w = .53;
v = .50;
y = .87 - v;
set(guicontrol('text',f,[x .90 w .06],'Performance'),'Fontweight','bold')
h = axes('Parent',f, ...
'Position',[x y w v], ...
'FontSize',8, ...
'Box','on');
end
end
function completeEpoch(obj,event)
global hList ...
hPlot ...
hCash ...
hTime ...
fileNames ...
fileFormats ...
colors ...
universeList ...
universeSize ...
portValue ...
portWeights ...
epochsTrain ...
epochCount
if portValue > 0
epochCount = epochCount + 1; set(hTime,'String',sprintf('Epoch: %d',epochCount))
updateUniverseData
if epochCount == epochsTrain
reviewPortfolioWeights
elseif epochCount > epochsTrain
computePortfolioReturn
reviewPortfolioWeights
end
else
abortStrategy(obj,event)
end
function updateUniverseData
global currentUniverseReturns
persistent previousUniversePrices
currentUniversePrices = 100 + .1*randn(universeSize,1);
if epochCount > 1
currentUniverseReturns = currentUniversePrices./previousUniversePrices - 1;
else
currentUniverseReturns = nan*currentUniversePrices;
end
f = fopen(fileNames{2},'at');
for i = 1:universeSize
fprintf(f,[fileFormats{2} '\n'],epochCount,universeList(i),currentUniversePrices(i));
end
fclose(f);
f = fopen(fileNames{3},'at');
for i = 1:universeSize
fprintf(f,[fileFormats{3} '\n'],epochCount,universeList(i),currentUniverseReturns(i));
end
fclose(f);
previousUniversePrices = currentUniversePrices;
end
function reviewPortfolioWeights
global portRetExp
[epoch,id,ret] = textread(fileNames{3},fileFormats{3});
movAvgReturn = nan(universeSize,1);
test1 = epoch >= epochCount - 5;
for i = 1:universeSize %#ok
test2 = id == universeList(i);
movAvgReturn(i) = nanmean(ret(test1 & test2));
end
[y,movAvgReturnRank] = sort(movAvgReturn);
goLong = movAvgReturnRank > (universeSize - 5);
goShort = movAvgReturnRank <= 5;
candWeights = zeros(universeSize,1);
candWeights(goLong) = 1/sum(goLong);
candWeights(goShort) = -1/sum(goShort);
if epochCount == epochsTrain
portWeights = candWeights;
end
er0 = portWeights'*movAvgReturn;
er1 = candWeights'*movAvgReturn;
if er1 > er0
portWeights = candWeights;
portRetExp = er1;
else
portRetExp = er0;
end
recordTrade
updateDisplay
function updateDisplay
j = 1;
for i = 1:universeSize %#ok
if portWeights(i) ~= 0
set(hList(j,1),'String',sprintf('%07d',universeList(i)))
set(hList(j,2),'String',sprintf('%+.2f',portWeights(i)), ...
'BackgroundColor',colors{2+sign(portWeights(i))})
j = j + 1;
end
end
end
function recordTrade
f = fopen(fileNames{5},'at');
for i = 1:universeSize %#ok
fprintf(f,[fileFormats{5} '\n'],epochCount,universeList(i),portWeights(i));
end
fclose(f);
end
end
function computePortfolioReturn
global currentUniverseReturns ...
portRetExp
portReturn = portWeights'*currentUniverseReturns;
portValue = portValue*(1 + portReturn);
f = fopen(fileNames{4},'at');
fprintf(f,[fileFormats{4} '\n'],epochCount,portReturn,portRetExp,portValue);
fclose(f);
updateDisplay
function updateDisplay
[epoch,ret,retexp,x] = textread(fileNames{4},fileFormats{4}); %#ok
w = 20; % size of moving window
n = length(epoch);
t = w*floor((n - 1)/w) + 1;
u = t + w - 1;
i = t:n;
h = plot(hPlot,i,ret(i),i,retexp(i));
set(h(1),'LineWidth',2,'Color',colors{2})
set(h(2),'LineWidth',2,'Color',colors{1})
set(legend('Realized return','Forecast return'),'Box','off')
set(hCash,'String',sprintf('Value: %.2f',portValue))
set(hPlot,'XLim',[t u])
end
end
end
function startStrategy(obj,event) %#ok
global fileNames ...
colors ...
epochTimer
set(obj,'Callback','','ForegroundColor',colors{1})
for i = 2:5
if exist(fileNames{i},'file')
delete(fileNames{i})
end
end
start(epochTimer)
end
function abortStrategy(obj,event) %#ok
global hStop ...
colors ...
epochTimer
set(hStop,'Callback','','ForegroundColor',colors{1})
stop(epochTimer)
delete(epochTimer)
end
function[varargout] = guicontrol(style,parent,pos,string)
h = uicontrol(...
'Parent',parent, ...
'Units','normalized', ...
'Position',pos, ...
'Style',style, ...
'String',string, ...
'FontSize',9,...
'HorizontalAlignment','center', ...
'BackgroundColor','w');
if nargout > 0
varargout(1) = {h};
end
end