classdef ExchangeTradedAsset < FM.Asset
% This source file is subject to version 3 of the GPL license,
% that is bundled with this package in the file LICENSE, and is
% available online at http://www.gnu.org/licenses/gpl.txt
%
% This source file can be linked to GPL-incompatible facilities,
% produced or made available by MathWorks, Inc.
properties
% Name of the exchange where the stock is listed (e.g. NYSE,
% NASDAQ, AMEX, etc)
Exchange = '';
% Symbol of the stock
Symbol = '';
end
properties (SetAccess = private, GetAccess = public)
% TimeSeries of the stock
TimeSeries = fints;
end
methods
function Sobj = ExchangeTradedAsset(symbol, exchange, class, category)
Sobj.AssetClass = class;
Sobj.AssetCategory = category;
Sobj.SupportedEvents = { 'UpdateAssetPrices' };
Sobj.Symbol = upper(symbol);
Sobj.Exchange = upper(exchange);
end
function ident = Ident(Sobj)
ident = sprintf('%s_%s_%s_%s', Sobj.AssetClass, Sobj.AssetCategory, Sobj.Symbol, Sobj.Exchange);
end
function ret = Plot(Sobj)
ret = false;
if (~isempty(ftsbound(Sobj.TimeSeries)))
chartfts(Sobj.TimeSeries);
ret = true;
end
end
function detail = Detail(Sobj)
detail = sprintf('Asset Class: %s\nAsset Category: %s\nSymbol: %s\nExchange: %s', Sobj.AssetClass, Sobj.AssetCategory, Sobj.Symbol, Sobj.Exchange);
dataAvail=ftsbound(Sobj.TimeSeries);
if (~isempty(dataAvail))
detail = sprintf('%s\nTime Series available for: %s :: %s\n', detail, datestr(dataAvail(1)), datestr(dataAvail(2)));
else
detail = sprintf('%s\nTime Series available for: NONE\n', detail);
end
end
function ret = ListenForEvent(Sobj, AUobj, event)
% Check if event is supported.
ret = false;
if ~(ismember(event, Sobj.SupportedEvents))
return;
end
switch upper(event)
case 'UPDATEASSETPRICES'
addlistener(AUobj, event, @Sobj.updateAssetPricesEvent);
ret = true;
otherwise
return;
end
end
function ret = GetPrice(Sobj, time, type)
try
datePrice = Sobj.TimeSeries(datestr(time,1));
if ~isempty(datePrice)
if ~exist('type', 'var')
ret = datePrice;
else
ret = fts2mat(datePrice.(upper(type)));
end
else
ret = -1;
return;
end
catch ME
ret = -1;
end
end
function ret = UpdatePrice(Sobj, startDate, endDate)
ret = false;
conn=yahoo;
if ~(isconnection(conn))
return;
end
stockData = fetch(conn, Sobj.Symbol, { 'Open', 'High', 'Low', 'Adj Close', 'Volume' }, datestr(startDate, 23), datestr(endDate, 23), 'd');
if (size(Sobj.TimeSeries) == 0)
Sobj.TimeSeries = fints(stockData(1:end,1), stockData(1:end,2:end), { 'OPEN', 'HIGH', 'LOW', 'CLOSE', 'VOLUME' }, 'd' );
else
newData = fints(stockData(1:end,1), stockData(1:end,2:end), { 'OPEN', 'HIGH', 'LOW', 'CLOSE', 'VOLUME' }, 'd' );
Sobj.TimeSeries = merge(Sobj.TimeSeries, newData);
end
Sobj.TimeSeries.desc = Sobj.Ident();
ret = true;
end
function assetFile = Save(Sobj, assetDir)
safeSymbol = regexprep(Sobj.Symbol, '(\W)', '');
eval(sprintf('%s = Sobj;', safeSymbol));
if (nargin == 1)
assetFile = [ Sobj.Exchange, '_', safeSymbol, '.mat' ];
else
assetFile = [ assetDir, '/', Sobj.Exchange, '_', safeSymbol, '.mat' ];
end
save(assetFile, safeSymbol);
end
% Override eq function to compare two exchange trades assets
function ret = eq(a, b)
if (strcmp(class(a), class(b)))
if (strcmp(a.Exchange, b.Exchange) && strcmp(a.Symbol, b.Symbol) && strcmp(a.AssetClass, b.AssetClass) && strcmp(a.AssetCategory, b.AssetCategory) )
ret = true;
else
ret = false;
end
else
ret = false;
end
end
end
methods (Access = private)
function ret = updateAssetPricesEvent(Sobj, eventSrc, eventData)
if (size(Sobj.TimeSeries) > 0)
datesbound = ftsbound(Sobj.TimeSeries);
startDate = addtodate(datesbound(2), 1, 'day');
endDate = now-1;
else
startDate = FM.Config.BackfillStartDate;
endDate = now-1;
end
ret = Sobj.UpdatePrice(startDate,endDate);
end
end
end