Showing posts with label IB matlab2ib. Show all posts
Showing posts with label IB matlab2ib. Show all posts

Friday, June 5, 2009

Convert Stock CUSIPs to Stock Symbols with a MATLAB program

UPDATE : Thanks to a comment, I changed the code to reflect the new changes at fidelity site.

CUSIP is a 9 character(alpha-numeric ) identifier. It actually stands for "Committee on Uniform Security Identification Procedures". Sometimes it is very useful to be able to look up the Stock Symbol that the CUSIP represents. I had a list of CUSIPS and some data associated with it. I did not have the Stock Symbols Associated with Them. I was only interested in Stock CUSIPS. I searched online and found out that there was no automated way of finding out the stock symbol associated with stock CUSIPS. So I wrote the following program to look up the CUSIP at the Fidelity website and grab the stock symbol associated with it. I extensively used regular expressions. I hope this program will be useful to others.

For example:
'031162100' given Amgen Inc---AMGN
Symbols = CusipToSymbolLookUp({'031162100';'03116210';})

function Symbols = CusipToSymbolLookUp(Cusip)
%CUSIPTOSYMBOLLOOKUP converts STOCK CUSIPS to STOCK Symbols
% Symbols = CusipToSymbolLookUp(Cusip) gives a list of STOCK symbols that
% correspond to a list of Cusips.
% This function looks up a STOCK symbol for a given CUSIP
% The CUSIP needs to be 8 or 9 characters long
% If a valid 8 character Cusip is given, then a 9th check digit is added if
% possible.It accesses the fidelity website and does html parsing
% to get the symbol name. Cusip can be a cell array of Cusips
% More information on CUSIPs can be found at:
% http://www.cusip.com
% I Thank Nabeel Azar for his program checkcusip.m
% Example:
% Symbols = CusipToSymbolLookUp({'031162100';'03116210';})

% Atleast one input is required
if(nargin < 1)
error('Atleast one Input is needed')
end
% Check if its either a cell array or Character
if~(ischar(Cusip)||iscell(Cusip))
error('Cusip needs to be either a character or Cell Array')
end

if(iscell(Cusip) && ~isvector(Cusip))
error('Cusip needs to be a cell array')
end

% Convert Char to a cell string
Cusip = cellstr(Cusip);

% Find how many cusips were given
ncusips = length(Cusip);

% Intial Web URL
weburl = ['http://activequote.fidelity.com/mmnet/SymLookup.phtml?reqforlookup=REQUESTFORLOOKUP&productid=mmnet&isLoggedIn=mmnet&rows=50&for=stock&by=cusip&criteria='];

% Pre assign the Output
Symbols = cell(ncusips,1);

% Now go through the List and do the processing
for idx = 1:ncusips

% If The Length of the Cusip is 8 digits/characters long,
% Then It is converted into 9 digits using a program called checkcusip
% If it returns a logical false, then it is a wrong CUSIP
% If it returns a double digit, then join the checkdigit to the
% original CUSIP

if(length(Cusip{idx})==8)
Result = checkcusip(Cusip(idx));
if (islogical(Result{1}) && Result{1}==false)
continue
else
% Join the Cusip with CheckDigit
Cusip{idx} = [Cusip{idx} num2str(Result{:})];
end

% If the Length is not equal to 9, then just continue
elseif(length(Cusip{idx})~=9)
continue
end

% Construct the URL using the Cusip and read the url
%[weburl Cusip{idx} '&submit=Search']
data = urlread([weburl Cusip{idx} '&submit=Search']);


% Search for a preliminary pattern
%pat = '<(a HREF).*?>.*?';
pat = 'SID_VALUE_ID=([a-zA-Z]+)">';

% Use regexp to match the pattern
data2=regexp(data,pat,'tokens');

% Use another pattern to get the symbol
if(~isempty(data2))
% pat = '>\w*<';
% sname=char(regexp(data2{1},pat,'match'));
Symbols(idx) = data2{1};
end

% % Pre-Process the Output before storing it in an array
% if(~isempty(sname))
% sname([1 end])='';
% Symbols{idx} = sname;
% end

end


function Result = checkcusip(inputCell)
%CHECKCUSIP Check a CUSIP
% CHECKCUSIP is used to validate 9 digit CUSIPs and
% provide the checkdigit for 8 digit CUSIPs.
%
% Note that if you give this function a combination of
% 8 and 9 digit CUSIPs, you need to check both the class
% (logical or non-logical) as well as the value of the
% output. Logicals are used to indicate validity of a
% 9 digit CUSIP, while non-logical doubles are used to
% supply the checkdigit for an 8 digit CUSIP.

% Convert the input to a char array
if iscell(inputCell)
cusipCharArray = strvcat(inputCell{:});
else
error(['Inputs must be cell arrays of CUSIP strings.'])
end


% Make sure there are at least 8 columns
if size(cusipCharArray,2)<8 p="">error(['Must supply 8 or 9 digit CUSIPs.']);
end

% Make them all lowercase
cusipCharArray = lower(cusipCharArray);




%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Convert the string digits to numerical values and
% the characters to their numerical values, with 'A':=10
% Set spaces (for computing the checkdigit) to NaNs

% Transpose the array, and work down the columns.
longCusipString = double(cusipCharArray);
longCusipString = longCusipString.';
numericalLocations = (longCusipString>='0' & longCusipString<='9');
charLocations = (longCusipString>='a' & longCusipString<='z');
NaNLocations = longCusipString==' ';

longCusipString(numericalLocations) = longCusipString(numericalLocations) - '0';
longCusipString(charLocations) = longCusipString(charLocations) - 'a' + 10;
longCusipString(NaNLocations) = NaN;

% Get the cusip digits
cusipNums = longCusipString(1:8,:);

% Scale with scaling factors
cusipNums = diag([1 2 1 2 1 2 1 2]) * cusipNums;

% Sum the digits in each term >=10;
gt_10 = cusipNums>=10;
cusipNums(gt_10) = floor(cusipNums(gt_10)/10) + rem(cusipNums(gt_10),10);

% Sum the resulting values
cusipNums = sum(cusipNums);

% Get the last digit
lastDigit = rem(cusipNums,10);

% Generate the checkdigit
checkDigit = 10 - lastDigit;
checkDigit(checkDigit==10) = 0;

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


% Create a cell array the right size for the output.
Result = cell(numel(inputCell),1);

% If no check digit was given in the input, output the checkdigit
if size(longCusipString,1)==9
needCusip = isnan(longCusipString(9,:));
else
needCusip = logical(ones(1,size(longCusipString,2)));
end
Result(needCusip) = num2cell(checkDigit(needCusip));

% If a check digit was given, validate it
if size(longCusipString,1)==9
isCheckdigitCorrect = longCusipString(9,~needCusip)==checkDigit(~needCusip);
Result(~needCusip) = num2cell(isCheckdigitCorrect);
end

% Only the 1st, 4th, 5th, or 6th digit may be an alphanumeric letter
% (1st for international issues)
badIdx = any(longCusipString([2 3 7 8],:)>=10,1);
Result(badIdx) = {logical(0)};

% The first digit cannot be an i, o, or z
badIdx = any(longCusipString(1,:)=='i' | longCusipString(1,:)=='o' | longCusipString(1,:)=='z',1);
Result(badIdx) = {logical(0)};

% Reshape the result
Result = reshape(Result,size(inputCell));

Sunday, July 27, 2008

Black Litterman Model in MATLAB (He & litterman implementation)

HeLitterman
MATLAB Implementation of Black Litterman Model

This code implements the Black and Litterman Model As given in the paper He & Litterman: The intuition Behind Black- Litterman
Model Portfolios.

% First The Inputs:

% Correlation Matrix: Page 18
Corrmat = ...
[1,0.4880,0.4780,0.5150,0.4390,0.5120,0.4910;
0.4880,1,0.6640,0.6550,0.3100,0.6080,0.7790;
0.4780,0.6640,1,0.8610,0.3550,0.7830,0.6680;
0.5150,0.6550,0.8610,1,0.3540,0.7770,0.6530;
0.4390,0.3100,0.3550,0.3540,1,0.4050,0.3060;
0.5120,0.6080,0.7830,0.7770,0.4050,1,0.6520;
0.4910,0.7790,0.6680,0.6530,0.3060,0.6520,1;];

% Risk Aversion Parameter---Page 10
RiskAversion = 2.5;

% Standard Deviations and Market Capitalization Weights--Table 2 Page 19
stdevs = ...
[16.0000
20.3000
24.8000
27.1000
21.0000
20.0000
18.7000]./100;

MktWeight = ...
[ 1.6000
2.2000
5.2000
5.5000
11.6000
12.4000
61.5000]./100;

tau = 0.05;

Market Equilibrium Risk Premiums : THE PI


Equation 2 Page 3 PI = RiskAversion * Covariance * MktWeight

% Need to Convert Correlation into Covariance

Covmat = Corrmat .* (stdevs * stdevs');

% Now we have everything to implement the Equation
%EqRiskPrem = RiskAversion * Covmat * MktWeight;
EqRiskPrem = RiskAversion * Covmat * MktWeight;
% Print Out Table 2 in Page 19
AssetNames = {'Australia','Canada','France','Germany','Japan',...
'UK','USA'};

Table2 = [{'Assets' 'Std Dev' 'Weq' 'PI'};
{'------' '------' '---' '--'};
AssetNames' num2cell([stdevs MktWeight EqRiskPrem]*100)]

Table2 =

'Assets' 'Std Dev' 'Weq' 'PI'
'------' '------' '---' '--'
'Australia' [ 16] [ 1.6000] [3.9376]
'Canada' [20.3000] [ 2.2000] [6.9152]
'France' [24.8000] [ 5.2000] [8.3581]
'Germany' [27.1000] [ 5.5000] [9.0272]
'Japan' [ 21] [11.6000] [4.3028]
'UK' [ 20] [12.4000] [6.7677]
'USA' [18.7000] [61.5000] [7.5600]

Views Based Optimal Weights

%View1 is The German Equity Market Will Outperform the rest of European

% Markets by 5% a year.
P = [ 0 %Australia
0 %Canada
-29.5 %France
100 %Germany
0 %Japan
-70.5 %UK
0]'./100; %USA

Q = 5/100;
% The Black Litterman Expected Returns are Calculated
% By Equation 8 and the Optimal Portfolio Weights are
% Calculated By
%RiskAversion * Covariance * ExpectedReturns(MU)
% Lambda = 0.302; Page 11

Omega = diag(diag(P*tau*Covmat*P'));


% Equation 8--Expected Returns : MU
PostCov = inv(inv(tau*Covmat) + (P' * inv(Omega) * P));
SigmaP = Covmat + PostCov;
ExpRet=inv(inv(tau*SigmaP)+P'*inv(Omega)*P)* ...
(inv(tau*SigmaP)*EqRiskPrem +P'*inv(Omega)*Q);
% ExpRet = inv(inv(tau*Covmat) + P' * inv(Omega) * P) * ...
%(inv(tau*Covmat) * EqRiskPrem + P' * inv(Omega) * Q);

% Optimal Weights
OptimalWeights = (1/RiskAversion)* inv(SigmaP) * ExpRet;

Tab4Col4 = OptimalWeights - (MktWeight)/(1+tau);

Table4 = [{'Assets' 'P' 'MU' 'W' 'W - Weq/1+tau'};
{'------' '--' '---' '--' '-------------'};
AssetNames' num2cell([P' ExpRet OptimalWeights ...
round(Tab4Col4 * 1000)./1000]*100)]

Table4 =

'Assets' 'P' 'MU' 'W' 'W - Weq/1+tau'
'------' '--' '---' '--' '-------------'
'Australia' [ 0] [ 4.3328] [ 1.5238] [ 0]
'Canada' [ 0] [ 7.5838] [ 2.0952] [ 0]
'France' [-29.5000] [ 9.2991] [-4.0555] [ -9]
'Germany' [ 100] [11.0615] [35.7733] [ 30.5000]
'Japan' [ 0] [ 4.5087] [11.0476] [ 0]
'UK' [-70.5000] [ 6.9550] [-9.7178] [ -21.5000]
'USA' [ 0] [ 8.0756] [58.5714] [ 0]





Friday, June 13, 2008

Trading Interactive Brokers with MATLAB

In This Blog, I will be writing about how to build automated trading systems using matlab and Interactive Brokers. I have previously worked as a Futures Trader and currently work as an Analyst in a Quantitative Strategies Team at a Hedge Fund of Fund.

My Main Interests are in building trading systems that take advantage of several Techniques such as Machine Learning, Artificial intelligence and Market Microstructure.