Code covered by the BSD License  

Highlights from
FinMetrics

  • fm(varargin) This source file is subject to version 3 of the GPL license,
  • AssetThis source file is subject to version 3 of the GPL license,
  • AssetUniverseThis source file is subject to version 3 of the GPL license,
  • AxlThis source file is subject to version 3 of the GPL license,
  • CashPositionThis source file is subject to version 3 of the GPL license,
  • CashTransactionThis source file is subject to version 3 of the GPL license,
  • Config This source file is subject to version 3 of the GPL license,
  • ConsoleMenuThis source file is subject to version 3 of the GPL license,
  • ConsoleMenuItemThis source file is subject to version 3 of the GPL license,
  • CurrencyAssetThis source file is subject to version 3 of the GPL license,
  • ExchangeTradedAssetThis source file is subject to version 3 of the GPL license,
  • FinMetricsThis source file is subject to version 3 of the GPL license,
  • PortfolioThis source file is subject to version 3 of the GPL license,
  • PositionThis source file is subject to version 3 of the GPL license,
  • StatisticsThis source file is subject to version 3 of the GPL license,
  • StockPositionThis source file is subject to version 3 of the GPL license,
  • StockTransactionThis source file is subject to version 3 of the GPL license,
  • TextUIThis source file is subject to version 3 of the GPL license,
  • TextUILocaleThis source file is subject to version 3 of the GPL license,
  • TextUIQuestionThis source file is subject to version 3 of the GPL license,
  • TextUIQuestionnaireThis source file is subject to version 3 of the GPL license,
  • TransactionThis source file is subject to version 3 of the GPL license,
  • View all files

FinMetrics

by

 

Open source/open architecture quantitative portfolio management environment.

Portfolio
classdef Portfolio < handle    
% 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 (SetAccess = private, GetAccess = public, Transient = true)
        Name = '';
        Transactions = {};
        Positions = {};
    end

    properties (Dependent = true)
        LastCommitedTransaction;
    end
    
    events (ListenAccess = 'public', NotifyAccess = 'private')
        PortfolioTransactionEvent
        PortfolioPositionEvent
    end
    
    methods
        % Get/set methods for properties.
        function set.Transactions(obj,value)            
            obj.Transactions = value;
            notify(obj, 'PortfolioTransactionEvent');            
        end
        
        function set.Positions(obj,value)            
            obj.Positions = value;
            notify(obj, 'PortfolioPositionEvent');            
        end
    end
   
    methods
        function Pobj = Portfolio(name)            
            Pobj.Name = name;
        end
        
        % Every time a new transaction is added to the log an ID is
        % assigned to it. Any further references to the transaction is
        % done through this ID. I cannot think of another way to identify a
        % transaction uniquely.
        
        function ret = AddTransaction(Pobj, newTransaction)
            if isempty(Pobj.Transactions)
                Pobj.Transactions = { newTransaction };            
            else               
                Pobj.Transactions = [ Pobj.Transactions; { newTransaction } ];                
            end        
            
            ret = size(Pobj.Transactions, 1);
        end
    
        function ret = get.LastCommitedTransaction(Pobj)
            ret = Pobj.getLastCommittedTrID();
        end
            
        function ListTransactions(Pobj)
            if (isempty(Pobj.Transactions) == false)
                for i=1:size(Pobj.Transactions,1),
                    fprintf('%d: %s\n', i, Pobj.Transactions{i}.Summary());
                end
            end            
        end
        
        function  ret = DeleteTransaction(Pobj, id)
            % Check if the specified id is valid and make sure the
            % transaction is not yet committed to the portfolio.
            ret = false;
            
            if (isempty(Pobj.Transactions) == true)                
                return;                
            elseif ((id < 1) || (id > size(Pobj.Transactions,1)))                    
                return;
            elseif (isempty(Pobj.Transactions{id}.CommittedOn) == false)
                % A committed transaction cannot be deleted from the log
                return;             
            end
                        
            Pobj.Transactions(id) = [];
            ret = true;
        end
        
        function ListPositions(Pobj)
            if (isempty(Pobj.Positions) == false)
                for i=1:size(Pobj.Positions,1),
                    fprintf('%d: %s\n', i, Pobj.Positions{i}.Summary());
                end
            end            
        end
              
        function ret = CommitTransaction(Pobj, id, cTime)
            % Check if the specified id is valid, make sure the
            % transaction is not yet committed to the portfolio, and the
            % order in transaction log of the transaction to be committed
            % is after the last committed.
            ret = false;
            
            if (isempty(Pobj.Transactions) == true)                
                return;                
            elseif ((id < 1) || (id > size(Pobj.Transactions,1)))                    
                return;
            elseif (isempty(Pobj.Transactions{id}.CommittedOn) == false) 
                return;             
            elseif (id <= Pobj.getLastCommittedTrID)
                return;
            end                                    
            
            if (Pobj.getLastCommittedTrID ~= 0)                
                if (floor(cTime) < floor(Pobj.Transactions{Pobj.getLastCommittedTrID}.CommittedOn))
                    return;
                end
            end
            
            % Assuming the transaction will be committed succesfully, we
            % set CommittedOn timestamp. That way we ensure the same
            % time is used for any resulting positions. If for some
            % reason transaction fails, CommittedOn will be cleared.            
            Pobj.Transactions{id}.CommittedOn = cTime;
            
            % Determine the type of transaction and call an appropriate
            % function.        
            switch class(Pobj.Transactions{id})
                case 'FM.StockTransaction'
                    ret = Pobj.commitStockTransaction(Pobj.Transactions{id});
                case 'FM.CashTransaction'
                    ret = Pobj.commitCashTransaction(Pobj.Transactions{id});
                otherwise
                    ret = false;
            end
            
            % Clear CommitedOn if transaction was not successful
            if (ret == false)
                Pobj.Transactions{id}.CommittedOn = '';
            else
                Pobj.Transactions{id}.PreviouslyCommittedOn = '';
                return;
            end
                        
        end
        
        function hold = Holdings(Pobj, params)
                hold = '';
                if (nargin < 2)
                    params = struct('ShortAsZero', false);
                end
                
                if (isempty(Pobj.Positions) == false)
                    for i=1:size(Pobj.Positions,1),
                        if isempty(hold)                                
                            if ((params.ShortAsZero == true) && (Pobj.Positions{i}.Quantity < 0))
                                hold = 0;
                            else
                                hold = Pobj.Positions{i}.Quantity;
                            end
                        else                                  
                            if ((params.ShortAsZero == true) && (Pobj.Positions{i}.Quantity < 0))
                                hold = [ hold; 0  ];                                    
                            else
                                hold = [ hold; Pobj.Positions{i}.Quantity ];                                    
                            end
                        end
                    end
                end       
        end
        
        function rets = TimeSeries(Pobj, params)
            % Find period with 100% data coverage
            rets = NaN;
            fullCoverage = '';            
            if (nargin < 2)
                params = struct();
            end

            if (isempty(Pobj.Positions) == false)
                for i=1:size(Pobj.Positions,1),
                    coverage = ftsbound(Pobj.Positions{i}.Asset.TimeSeries);
                    if isempty(coverage)                         
                        return;
                    end
                    
                    if isempty(fullCoverage)
                        fullCoverage = coverage;
                    else
                        if (fullCoverage(1) < coverage(1))
                            fullCoverage(1) = coverage(1);
                        end
                        
                        if (fullCoverage(2) > coverage(2))
                            fullCoverage(2) = coverage(2);
                        end
                    end                                            
                end                                
            end
                        
            if (~isfield(params, 'StartDate'))
                params.StartDate = fullCoverage(1);
            elseif (params.StartDate < fullCoverage(1))
                params.StartDate = fullCoverage(1);
            end
            
            if (~isfield(params, 'EndDate'))
                params.EndDate = fullCoverage(2);
            elseif (params.EndDate > fullCoverage(2))
                params.EndDate = fullCoverage(2);
            end
            
            if (~isfield(params, 'PriceSeries'))
                params.PriceSeries = 'CLOSE';
            end
            
            % check if startDate < endDate
            if (params.StartDate > params.EndDate)                
                return;
            end
            
            % compose string date range for FTS
            range = sprintf('%s::%s', datestr(params.StartDate,2), datestr(params.EndDate,2));
            rets = '';

            if (isempty(Pobj.Positions) == false)
                for i=1:size(Pobj.Positions,1),
                    % get Time Series
                    cmd = sprintf('assetSeries=chfield(Pobj.Positions{%d}.Asset.TimeSeries.%s(''%s''), ''%s'', ''%s'');', i, params.PriceSeries, range, params.PriceSeries,Pobj.Positions{i}.Asset.Ident);
                    try
                        eval(cmd);            
                    catch ME                        
                        display(sprintf('Failed to generate time series for asset ''%s'' for period ''%s''.', Pobj.Positions{i}.Asset.Ident, range)); 
                        continue;
                    end

                    if isempty(rets)
                                rets = assetSeries;                            
                        else                                  
                                rets = [ rets assetSeries  ];                                    
                    end
                end
            end     
        end
        
        function ret = UnCommitTransaction(Pobj, id)
            % Enough for today, ready to write uncommit cash transaction
            % and GetPositionTransactions for cash. In both cases replace
            % class type detection with switch logic.
            
            % Check if the specified id is valid and make sure the
            % transaction is committed to the portfolio. Only last commited
            % transaction in th log can be uncommitted.
            ret = false;
            
            if (isempty(Pobj.Transactions) == true)                
                return;                
            elseif ((id < 1) || (id > size(Pobj.Transactions,1)))                    
                return;
            elseif (isempty(Pobj.Transactions{id}.CommittedOn) == true)
                return;
            elseif (id ~= Pobj.getLastCommittedTrID)
                return;            
            end

            % Determine the type of transaction and call an appropriate
            % function.        
            if (strcmp(class(Pobj.Transactions{id}), 'FM.StockTransaction'))
                ret = Pobj.uncommitStockTransaction(Pobj.Transactions{id}); 
            elseif (strcmp(class(Pobj.Transactions{id}), 'FM.CashTransaction'))
                ret = Pobj.uncommitCashTransaction(Pobj.Transactions{id}); 
            end
            
            if (ret == true)
                Pobj.Transactions{id}.PreviouslyCommittedOn = Pobj.Transactions{id}.CommittedOn;
                Pobj.Transactions{id}.CommittedOn = '';
            end
            
        end

        function ret = GetPositionTransactions(Pobj, id)
            % NOT sure if this function should be public.
            % Check if the specified position id is valid
            ret = '';
            if (isempty(Pobj.Positions) == true)                
                return;                
            else
                if ((id < 1) || (id > size(Pobj.Positions,1)))
                    return;
                end
            end
            ret = Pobj.getPositionTransactions(id);

        end
          
        function ret = ValuePosition(Pobj, id, eop)        
            % Check if the specified position id is valid
            ret = false;
            if (isempty(Pobj.Positions) == true)                
                return;                
            else
                if ((id < 1) || (id > size(Pobj.Positions,1)))
                    return;
                end
            end
            % Determine the type of position and call an appropriate
            % function.        
            if (strcmp(class(Pobj.Positions{id}), 'FM.StockPosition'))
                ret = Pobj.valueStockPosition(id, eop);
                return;
            end                    
        end        
        
        function ret = ListPositionTransactions(Pobj, id)
            % Check if the specified position id is valid
            ret = false;
            if (isempty(Pobj.Positions) == true)                
                return;                
            elseif ((id < 1) || (id > size(Pobj.Positions,1)))
                return;
            end
            
            Ptrns = Pobj.GetPositionTransactions(id);
                for i=1:size(Ptrns,1),
                    fprintf('%d: %s\n', i, Ptrns{i}.Summary());
                end
            ret = true;
        end
        
        function ret = SyncAssetsWithUniverse(Pobj, AUObj)
            % We will look through portfolio's transactions and positions, 
            % obtain the underlying asset and try to find it in the Universe's Assets
            % property. If asset is found in the universe, the asset
            % reference for the transaction or position will be repointed to the
            % universe. If asset is not found in universe, it will be
            % imported to the universe via AUObj.AddAsset, and the pointer
            % updated for the transaction or position.
            
            ret = false;
            
            % First, update all transactions
            if (size(Pobj.Transactions,1) == 0)
                return;
            end
            
            for i=1:size(Pobj.Transactions,1),
                aID = AUObj.isAssetIn(Pobj.Transactions{i}.Asset);
                                
                if (aID > 0)
                    Pobj.Transactions{i}.UpdateAsset(AUObj.Assets{aID});
                else
                    aIDn = AUObj.AddAsset(Pobj.Transactions{i}.Asset);                    
                    Pobj.Transactions{i}.UpdateAsset(AUObj.Assets{aIDn});                    
                end                    
            end

            
            % Next update all Positions
            if (size(Pobj.Positions,1) == 0)
                ret = true;
                return;
            end
            
            for i=1:size(Pobj.Positions,1),
                aID = AUObj.isAssetIn(Pobj.Positions{i}.Asset);
                                
                if (aID > 0)
                    Pobj.Positions{i}.UpdateAsset(AUObj.Assets{aID});
                else
                    aIDn = AUObj.AddAsset(Pobj.Positions{i}.Asset);                    
                    Pobj.Positions{i}.UpdateAsset(AUObj.Assets{aIDn});
                end                    
            end
            
            ret = true;
        end
        
        function newObj = saveobj(Pobj)
            newObj = struct('Name', Pobj.Name, 'Transactions', { Pobj.Transactions }, 'Positions', { Pobj.Positions});
        end                        
        
        function ret = Value(Pobj, params)
            ret = NaN;

            if (nargin < 2)
                params = struct();
            end
            
            if (~isfield(params, 'ShortAsZero'))
                params.ShortAsZero = false;
            end

            portSeries = Pobj.TimeSeries(params);                        
            portHoldings = Pobj.Holdings(struct('ShortAsZero', params.ShortAsZero));
            portValues = fts2mat(portSeries) * portHoldings;
            ret = fints(portSeries.dates, portValues, { 'Value' }, 'd', Pobj.Name);
        end
    end
        
    methods (Access = private)
        function ret = valueStockPosition(Pobj, id, eop)        
            
            allTrans = Pobj.getPositionTransactions(id);
            trans = {};
            lastEnt = Pobj.Positions{id}.Asset.TimeSeries(size(Pobj.Positions{id}.Asset.TimeSeries,1));
            
            if (eop > lastEnt.dates)
                eop = lastEnt.dates;
            end
            
            for q = 1:size(allTrans,1)
                if (allTrans{q}.CommittedOn <= eop)
                    if isempty(trans)                        
                        trans = { allTrans{q} };
                    else
                        trans = [ trans; { allTrans{q} }];
                    end
                end
            end
            
            t=size(trans,1);
            
            if (t == 0)
                ret = false;
                return;
            end
            
            posTimeSeries = {};                      
            quant = 0;
            
            while (t > 0)              
                    if (t > 1)
                        dateIndex = sprintf('%s::%s', datestr(trans{t}.CommittedOn,2), datestr(trans{t-1}.CommittedOn,2));
                    else                        
                        dateIndex = sprintf('%s::%s', datestr(trans{t}.CommittedOn,2), datestr(eop,2));
                    end
                    
                    switch upper(trans{t}.Action)
                        case 'BUY'
                            quant = quant + trans{t}.Quantity;
                        case 'SELL'
                            quant = quant - trans{t}.Quantity;
                        case 'SELL SHORT'
                            quant = quant - trans{t}.Quantity;
                        case 'BUY TO COVER'
                            quant = quant + trans{t}.Quantity;
                    end
                    fprintf('%s - %d\n', dateIndex, quant);                                                                
                    try
                        posTimeSeries = Pobj.Positions{id}.Asset.TimeSeries(dateIndex);
                        posTimeSeries  = [ [posTimeSeries.OPEN, posTimeSeries.HIGH, posTimeSeries.LOW, posTimeSeries.CLOSE] * quant, posTimeSeries.VOLUME ];
                        fprintf('Quantity try: %d\n', quant);
                        
                        if ~exist('aggrSeries', 'var')                            
                            if (t > 1) && (size(posTimeSeries,1) > 1)
                                aggrSeries = posTimeSeries(1:size(posTimeSeries,1)-1);
                            else
                                aggrSeries = posTimeSeries(1:size(posTimeSeries,1));
                            end
                        else
                            if (t > 1) && (size(posTimeSeries,1) > 1)
                                aggrSeries = [ aggrSeries; posTimeSeries(1:size(posTimeSeries,1)-1) ];
                            else
                                aggrSeries = [ aggrSeries; posTimeSeries(1:size(posTimeSeries,1)) ];
                            end
                        end                        
                    catch ME
                        fprintf('Quantity catch: %d\n', quant);
                        ret = aggrSeries;
                        aggrSeries.desc = Pobj.Positions{id}.Asset.Ident();                        
                        return;
                    end                    
                    t = t - 1;                
            end

            aggrSeries.desc = Pobj.Positions{id}.Asset.Ident();            
            ret = aggrSeries;            
        end
        
        function new = copy(InObj)        
            tmpFile = 'objtmp';
            save(tmpFile, 'InObj');
            tmpObj = load([tmpFile, '.mat']);
            new = tmpObj.(char(fieldnames(tmpObj)));
            delete([tmpFile, '.mat']);
        end

        % isAssetin checks if portfolio already has a position in the
        % specified asset and trade direction
        function res = isAssetin(Pobj, asset, dir)
            res = false;
            
            if isempty(Pobj.Positions)
                return;
            end
            
            for t=1:size(Pobj.Positions,1),                
                if ((asset == Pobj.Positions{t}.Asset) && strcmpi(Pobj.Positions{t}.Direction, dir))
                        res = true;
                        break;
                end                
            end
        end
        
        % getPositionID returns the position id in Pobj.Positions cell
        % array which matches the underlying asset and the direction of
        % trade.
        function res = getPositionID(Pobj, asset, dir)
            res = 0;
            
            for t=1:size(Pobj.Positions,1),
                if ((asset == Pobj.Positions{t}.Asset) && strcmpi(Pobj.Positions{t}.Direction, dir))
                    res = t;
                    break;
                end
            end
        end
        
        function addPosition(Pobj, newPosition)
            if isempty(Pobj.Positions)
                Pobj.Positions = { newPosition };
            else               
                Pobj.Positions = [ Pobj.Positions; { newPosition } ];    
            end                                    
        end
        
        function deletePosition(Pobj, id)
            if (isempty(Pobj.Positions(id)) == false)
                Pobj.Positions(id) = [];
            end
        end
        
        function ret = commitStockTransaction(Pobj, Strns)
            
            switch upper(Strns.Action)
                case 'BUY'
                    switch Pobj.isAssetin(Strns.Asset, Strns.GenPosition.Direction)
                        case true
                            posID = Pobj.getPositionID(Strns.Asset, Strns.GenPosition.Direction);
                            Pobj.Positions{posID} = Pobj.Positions{posID} + Strns.GenPosition;                            
                        case false                            
                            % Generate position based on transaction and
                            % assign transaction time to OpenDate property.
                            nPos = Strns.GenPosition;
                            if isempty(Strns.Openning)
                                nPos.OpenDate = Strns.CommittedOn;                            
                            else
                                nPos.OpenDate = Strns.Openning.CommittedOn;
                            end
                            
                            Pobj.addPosition(nPos);                            
                    end                    
                case 'SELL'
                    switch Pobj.isAssetin(Strns.Asset, Strns.GenPosition.Direction)
                        case true
                            posID = Pobj.getPositionID(Strns.Asset, Strns.GenPosition.Direction);
                            
                            % Check if the sell order does not exceed the
                            % existing long position
                            if ((Pobj.Positions{posID} + Strns.GenPosition) == false)                                
                                ret = false;
                                return;                            
                            else
                                
                                Pobj.Positions{posID} = Pobj.Positions{posID} + Strns.GenPosition;
                                if (abs(Pobj.Positions{posID}.Quantity) <= FM.Config.FloatTol)                                
                                    trns = Pobj.GetPositionTransactions(posID);
                                    Strns.Openning = trns{size(trns, 1)};
                                    Pobj.deletePosition(posID);                                    
                                end
                            end
                        case false
                            ret = false;
                            return;                            
                    end                    

                case 'SELL SHORT'
                    switch Pobj.isAssetin(Strns.Asset, Strns.GenPosition.Direction)
                        case true                            
                            posID = Pobj.getPositionID(Strns.Asset, Strns.GenPosition.Direction);
                            Pobj.Positions{posID} = Pobj.Positions{posID} + Strns.GenPosition;                                                        
                        case false                            
                            % Generate position based on transaction and
                            % assign current time to OpenDate property.
                            nPos = Strns.GenPosition;
                            if isempty(Strns.Openning)
                                nPos.OpenDate = Strns.CommittedOn;                            
                            else
                                nPos.OpenDate = Strns.Openning.CommittedOn;
                            end
                            
                            Pobj.addPosition(nPos);
                    end
                case 'BUY TO COVER'
                    switch Pobj.isAssetin(Strns.Asset, Strns.GenPosition.Direction)
                        case true
                            posID = Pobj.getPositionID(Strns.Asset, Strns.GenPosition.Direction);
                            
                            % Check if the order to cover does not exceed
                            % the outstanding short position
                            if ((Pobj.Positions{posID} + Strns.GenPosition) == false)                                
                                ret = false;
                                return;                            
                            else
                                Pobj.Positions{posID} = Pobj.Positions{posID} + Strns.GenPosition;
                                if (Pobj.Positions{posID}.Quantity == 0)
                                    trns = Pobj.GetPositionTransactions(posID);
                                    Strns.Openning = trns{size(trns, 1)};

                                    Pobj.deletePosition(posID);                                   
                                end

                            end                            
                        case false
                            ret = false;
                            return;                            
                    end                    
                otherwise
                    ret = false;
                    return;
            end
                        
            ret = true;
        end
                        
        function ret = uncommitCashTransaction(Pobj, Ctrns)
            ret = false;            
            Rtrns = Ctrns.Reverse;
            
            if (isempty(Rtrns))
                return;
            elseif (commitCashTransaction(Pobj, Rtrns) == false)
                return;
            else
                ret = true;                
            end                        
        end
        
        function ret = uncommitStockTransaction(Pobj, Strns)
            ret = false;            
            Rtrns = Strns.Reverse;
            
            if (isempty(Rtrns))
                return;
            elseif (commitStockTransaction(Pobj, Rtrns) == false)
                return;
            else
                ret =true;                
            end                        
        end
                
        function ret = getPositionTransactions(Pobj, id)
            % The function returns a list of transactions related to the
            % given position using the OpenDate property as the starting
            % point.
                       
            ret = '';
            t = size(Pobj.Transactions, 1);                  
            
            while ( t >= 1)
                % First check if transaction is Committed, skip it if not
                if (isempty(Pobj.Transactions{t}.CommittedOn) == true)
                    t = t - 1;
                    continue;
                end
                
                % Check if transaction CommittedOn timestamp is gt
                % position's OpenDate                
                if (Pobj.Transactions{t}.CommittedOn < Pobj.Positions{id}.OpenDate)
                    break;
                end
                
                tPos = Pobj.Transactions{t}.GenPosition;
                
                if ((Pobj.Positions{id}.Asset == tPos.Asset) && (strcmpi(Pobj.Positions{id}.Direction, tPos.Direction)))
                       if (size(ret,1) == 0)
                           ret = { Pobj.Transactions{t} };
                       else
                           ret = [ ret; { Pobj.Transactions{t} } ];
                       end
                end            
                t = t - 1;                                
            end                      
        end
    
        function ret = getLastCommittedTrID(Pobj)
            ret = 0;
            t = size(Pobj.Transactions, 1);
            while (t >= 1)
                if (isempty(Pobj.Transactions{t}.CommittedOn) == false)
                    ret = t;
                    break;
                end
                t = t -1;                
            end
        end
        
        function ret = commitCashTransaction(Pobj, Strns)                    
            
            switch upper(Strns.Action)
                case {'DEPOSIT', 'CREDIT' }
                    switch Pobj.isAssetin(Strns.Asset, Strns.GenPosition.Direction)
                        case true
                            posID = Pobj.getPositionID(Strns.Asset, Strns.GenPosition.Direction);
                            Pobj.Positions{posID} = Pobj.Positions{posID} + Strns.GenPosition;                            
                        case false                            
                            % Generate position based on transaction and
                            % assign transaction time to OpenDate property.
                            nPos = Strns.GenPosition;                            

                            if isempty(Strns.Openning)
                                nPos.OpenDate = Strns.CommittedOn;                            
                            else
                                nPos.OpenDate = Strns.Openning.CommittedOn;
                            end

                            Pobj.addPosition(nPos);                            
                    end                    
                case {'WITHDRAWAL', 'DEBIT' }
                    switch Pobj.isAssetin(Strns.Asset, Strns.GenPosition.Direction)
                        case true
                            posID = Pobj.getPositionID(Strns.Asset, Strns.GenPosition.Direction);
                            
                            % Check if the sell order does not exceed the
                            % existing long position
                            if ((Pobj.Positions{posID} + Strns.GenPosition) == false)                                
                                ret = false;
                                return;                            
                            else
                                
                                Pobj.Positions{posID} = Pobj.Positions{posID} + Strns.GenPosition;
                                if (abs(Pobj.Positions{posID}.Quantity) <= FM.Config.FloatTol)
                                    trns = Pobj.GetPositionTransactions(posID);
                                    Strns.Openning = trns{size(trns, 1)};
                                    
                                    Pobj.deletePosition(posID);                                    
                                end
                            end
                        case false
                            ret = false;
                            return;                            
                    end     
                otherwise
                    ret = false;
                    return;
            end                        
            ret = true;
        end                    
        
    end
    
    methods (Static)
      function newObj = loadobj(obj)
         if isstruct(obj)            
            newObj = FM.Portfolio(obj.Name);            
            newObj.Name = obj.Name;
            newObj.Transactions = obj.Transactions;
            newObj.Positions = obj.Positions;                                  
         end
      end
    end
    
end % classdef

Contact us