NAME

    Finance::StockAccount - Analyze past transactions in a personal stock
    account.

VERSION

    Version 0.01

SYNOPSIS

    Analyze past transactions in a personal stock account. Find out your
    total profit, annual profit, quarterly profit, monthly profit, or
    profit for any other arbitrary date/time range. Discover what the most
    cash you had invested in stocks at once was, over the course of your
    account from when it opened to the present, or for any period. Or get
    the total cash you spent on all stock purchases, call that your
    totalOutlays and learn how the ratio of profit to that totalOutlays
    changed from period to period. Find out how much you spent on
    commissions. Match up the results with your experience by looking at
    profit for each stock symbol separately.

        use Finance::StockAccount;
    
        # Object-oriented, so instantiate your object
        my $sa = Finance::StockAccount->new();
    
        # Now add your trades
        # One (fake/fantasy) trade a day for a week in January...
        $sa->stockTransaction({ # total outlay: 1000
            symbol          => 'AAA',
            dateString      => '20140106T150500Z', # This is a Time::Moment string, more on that below
            action          => 'buy',              # in the 'Required: date' section
            quantity        => 198,
            price           => 5,
            commission      => 10,
        });
        $sa->stockTransaction({ # total outlay: 1000
            symbol          => 'BBB',
            dateString      => '20140107T150500Z',
            action          => 'buy',
            quantity        => 99,
            price           => 10,
            commission      => 10,
        });
        $sa->stockTransaction({ # total revenue: 600
            symbol          => 'AAA',
            dateString      => '20140108T150500Z',
            action          => 'sell',
            quantity        => 100,
            price           => 6.10,
            commission      => 10,
        });
        $sa->stockTransaction({ # total revenue: 1070
            symbol          => 'BBB',
            dateString      => '20140109T150500Z',
            action          => 'sell',
            quantity        => 99,
            price           => 11,
            commission      => 19,
        });
        $sa->stockTransaction({ # total revenue: 670
            symbol          => 'AAA',
            dateString      => '20140110T150500Z',
            action          => 'sell',
            quantity        => 98,
            price           => 7,
            commission      => 16,
        });
    
        # How much did you make (or lose)?
        $sa->profit();                    # 340
    
        # What was the most cash you had invested in stocks at once?
        $sa->maxCashInvested();           # 2000
    
        # How much profit did you make as a share of the max you invested?
        $sa->profitOverMaxCashInvested(); # 0.17
    
        # Prefer just profit over outlays?  No problem.  It happens to be the same in this case.
        $sa->profitOverOutlays();         # 0.17
    
        # If you kept up that rate of profit over a year how much would you make?
        $sa->profitOverYears();           # 31046.25 (Wish I were that lucky.)
    
        # How much did you pay your broker?
        $sa->commissions();               # 65
    
        # How many transactions were counted in these statistics?
        $sa->numberOfTrades();            # 5
    
        # Get a list of statistics you can loop through
        my $stats = $sa->stats();
    
        # or get it broken down by date period
        $sa->annualStats();
        $sa->quarterlyStats();
        $sa->monthlyStats();
    
        # Want me to iterate through it and make it a string for you?
        print $sa->statsString();
    
        # Want that by date too?
        print $sa->annualStatsString();
        print $sa->quarterlyStatsString();
        print $sa->monthlyStatsString();
    
        # Get a simple one-stock-per-line breakdown of how you did
        print $sa->summaryByStock();
    
        # Need to exclude a couple stocks from analysis?
        $sa->skipStocks(qw(AAA BBB));
    
        # Include AAA and BBB again
        $sa->resetSkipStocks();
    
        # Curious how the module is doing its accounting?
        # Print the realizations (matches of acquisitions to divestment):
        print $sa->realizationsString();

    My online brokerage account does not allow me to easily see how my
    stock account is performing. With a little research, I found this was
    common practice with both online and offline brokerages, as well as
    financial advisers. So I wrote this software to find out my actual
    account performance, and shared these modules so others could find out
    theirs.

    This is a pure stock-transaction based set of modules. Currently
    understood transaction types include buy, sell, short, and cover. This
    version (version 0.01) does not consider cash or dividends, but I would
    like to add those features in future releases. Because of that
    limitation, calculations cannot be based purely on cash -- but rather
    on appreciation and depreciation of stocks, and timing of transactions
    -- which gives an interesting (and I think useful) perspective on
    account performance.

    Looking at the "Analyze" tools in my OptionsXpress online brokerage
    account, I saw it always used a "Last In, First Out" accounting method,
    which, frankly, is ridiculous in terms of evaluating my stock trading
    performance.

    So in these modules, accounting is done by what I call the Greatest
    Realized Benefit (GRB) method: divestments (sales and covers) are
    processed from oldest to newest, and one or more prior acquisitions
    (buys and shorts) are matched with the sale by availability (meaning
    not all acquisition shares are already tied to another divestment) and
    lowest cost of the acquisition. Future releases may add alternative
    accounting methods that could be selected by the user, and I welcome
    your suggestions for those.

    Along the way I tried to create a pure stock transaction class and a
    pure stock class. If you need such a thing, please look at

        Finance::StockAccount::Transaction
        Finance::StockAccount::Stock

    which are included in the Finance::StockAccount installation.

    If you happen to have an OptionsXpress online brokerage account you can
    import the whole thing in one go with
    Finance::StockAccount::Import::OptionsXpress. I would like to add more
    formats, so, if you can, please donate an export from a brokerage
    account to help this along.

    Dates are stored as Time::Moment objects, and may be specified either
    as a Time::Moment object (using the 'tm' property) or one of the string
    formats natively understood by Time::Moment (using the 'dateString'
    property).

EXPLANATION

    This set of modules is intended to give the lay investor (as opposed to
    the high finance Wall Street type who already has a bunch of expensive
    tools available to him) a meaningful sense of how his or her personal
    stock account is doing. It turns out a lot of both online and offline
    brokerages and financial advisers and institutions obscure that
    information from their users on the theory that if you knew how you
    were really doing, you would take your money elsewhere, or bug them
    with questions and demands for improvement. So to get the information
    from them, you have to get the data, make a plan, and do some
    accounting and some math. It's one more thing on the to-do list so many
    people don't get to it with any frequency.

    With these modules you can get a better understanding of the
    performance of your personal stock account. Here's what you do: Create
    a new stock account object, add your past stock transactions to it, and
    get statistics and information from it. You can set arbitrary date
    limits, to constrain that information to a certain period, or use built
    in methods for yearly, quarterly, or monthly data.

    This set of modules deals purely in stock transactions. There is no
    concept of cash transactions. Currently there is not even a concept of
    dividends, though I intend to add that in a future release. So far it
    is purely concerned with acquisitions and divestments: their timing,
    absolute value, and relative value.

 Terminology

   Acquisition

    A stock transaction of the type 'buy' or 'short'. This is where the
    consumer (or user) spends cash to gain an interest in some number of
    shares of a stock, buying it if she expects it to go up, shorting it if
    she expects it to go down.

    An acquisition, or part of an acquisition, becomes the cost basis for a
    later divestment.

   Divestment

    A stock transaction of the type 'sell' or 'cover'. This is where the
    consumer sells her interest in a stock in return for cash, terminating
    the interest gained in an earlier acquisition for some number of shares
    and gaining cash as a result.

   Realization

    These modules attempt to match each divestment against one or more
    prior acquisition(s), and use that match to calculate profit and other
    statistics useful for evaluating stock account performance. A
    successful match between a divestment and one or more acquisitions is
    called a "realization" because it represents the consummation or
    realization of the totalOutlays.

   Set

    The collection of all realizations for a particular stock.

   Outlay

    How much cash was spent on an acquisition transaction, including
    commissions and fees.

   Revenue

    How much cash was received in a divestment, after commissions and fees
    have been subtracted.

 Statistics, or "Why does that number look wrong?"

    Unmatched transactions are not included in statistics: an acquisition
    that cannot be paired with a divestment, or a divestment that cannot be
    paired with an acquisition, is simply left out or ignored. Here's an
    example to illustrate why this is necessary: Suppose you bought $5,000
    worth of stock 'FOO', but you haven't sold it yet. There is no way to
    evaluate whether that was a profitable choice or not. It could end up
    making you a millionaire, or its value could drop to $0.

    So when you see some statistics that look different from what you
    expected, one of the things you might consider is whether any
    transactions were left out of the analysis. You can check that with the
    numberOfTrades and numberExcluded methods (see below). If you want more
    granular information, you might consider diving down to the
    Finance::StockAccount::Set level, which provides more tools for looking
    at the accounting of all trades in a specific stock.

    Another area that might appear off at first inspection is the periodic
    stats. This module handles date range limitations by figuring out what
    portion of a given realization to attribute to the date range. Imagine,
    for example, you purchase a stock at d1 and sell it at d2. Then you set
    a date range limit starting at s1 and ending at s2 on this time line:

            s1                                                   s2
        |---|----------------------------------------------------|---|
        d1                                                           d2

    Trades on d1 and d2 are outside the date range limit set by s1 and s2.
    So a simple evaluation would attribute no value to that realization
    within this time line. But the reality is that most of the value of
    that realization likely accrued during this time. It's also a
    simplification, since I don't look up the stock price for that stock
    every day during that time, but this module assumes a linear change in
    value and attributes to date range s1 to s2 a value for this
    realization in proportion to the time it overlaps with the range d1 to
    d2. So $sa->profit() with this date range limit would return the profit
    for the entire realization times (s2-s1)/(d2-d1). Commissions, outlays,
    revenues, etc., are all divided up the same way.

    Perhaps the most practical application for this rule is the periodic
    look at your stock performance. So when you look at annualStats,
    quarterlyStats, or monthlyStats, you will see what I would consider
    more accurate divisions of value. And a month where you did no trades
    would not necessarily mean a month with no stats, as acquisitions would
    likely be gaining or losing value.

    This can have the odd-looking side effect, however, of showing you a
    number of trades considered in the statistics gathering that is larger
    than the number of trades actually made within that date range. And it
    means the purported "number of trades" for each period adds up to more
    than the total number of trades in the account. I may try to remove
    this side effect in a future version, so let me know if you find it too
    problematic or confusing...

METHODS

 new

    Constructor, instantiates and returns a new Finance::StockAccount
    object. Typically called with no arguments:

        my $sa = Finance::StockAccount->new();

    Currently there is only one StockAccount option/setting, which may be
    passed to new if desired. By default, attempts to add a stock
    transaction with a zero price to a StockAccount object will be treated
    as suspect and fail. I realize that is personal preference, so it may
    optionally be overcome by setting allowZeroPrice, like so:

        my $sa = Finance::StockAccount->new({allowZeroPrice => 1});

    This option can also be set via method (see allowZeroPrice method
    below).

 stockTransaction

    This is the intended means of adding transactions to a StockAccount
    object. An instantiation hash is passed in. Here is an example, me
    buying fifty shares of stock in Twitter:

        $sa->stockTransaction({
            symbol          => 'TWTR',
            dateString      => '20140708T185304Z',
            action          => 'buy',
            quantity        => 50,
            price           => 37.33,
            commission      => 8.95,
        });

    Several pieces of information are required.

    Required: stock

    For one, there must be a stock. It may be specified as a symbol string,
    as above. An optional exchange string may be passed in as well:

            symbol          => 'TWTR',
            exchange        => 'NYSE', # optional

    Alternatively, a stock object can be created using
    Finance::StockAccount::Stock and passed in with the stock key:

        use Finance::StockAccount;
    
        my $stock = Finance::StockAccount::Stock->new({
            symbol          => 'TWTR',
            exchange        => 'NYSE', # optional
        });
        $sa->stockTransaction({
            stock           => $stock,
            ...
        });

    The same $stock object could then be used over and over to pass in
    transactions on that stock. But even if you use a symbol string each
    time, they will be treated as the same stock. An exchange modifies a
    stock, so you could have two stocks with the same symbol traded on two
    different exchanges and they would be kept separate in StockAccount
    accounting.

    Required: date

    Second, there must be a date for the transaction. Dates are necessary
    for matching a sale to its prior purchase, or for calculating the mean
    annual profit (or loss), for example. Finance::StockAccount uses the
    CPAN module Time::Moment to handle dates. A date can either be passed
    in as a string using the dateString key:

            dateString      => '20140708T185304Z',

    or a Time::Moment object can be passed in using the tm key:

        my $tm = Time::Moment->new({ # the same date as the string above
            year        => 2014,
            month       => 7,
            day         => 8,
            hour        => 18,
            minute      => 53,
            second      => 4,
            offset      => 0,
        });
        $sa->stockTransaction({
            symbol          => 'TWTR',
            tm              => $tm,
            ...
        });

    If using a string passed in with the dateString key, any string
    acceptable to the Time::Moment->from_string method without using the
    'lenient' flag will work. Please see the perldoc for Time::Moment for
    more information.

    I chose to use Time::Moment over other Perl time modules because of its
    efficiency in benchmark tests and its ease of use. It seemed to do
    everything I needed, to do it correctly, and to do it faster than any
    of the alternatives. Please give it a chance, but also please do let me
    know if you run into any problems using it in the context of this
    module.

    Required: action

    A value for the 'action' key is required and must be one of the
    following strings: 'buy', 'sell', 'short', or 'cover'. E.g.:

        $sa->stockTransaction({
            ...
            action  => 'sell',
            ...
        });

    Required: quantity

    A numeric value for quantity greater than zero is required:

        $sa->stockTransaction({
            ...
            quantity    => 60,
            ...
        });

    Required: price

    A numeric value for price is also required:

        $sa->stockTransaction({
            ...
            price    => 4.55,
            ...
        });

    By default, the price is required to be greater than zero, but see the
    'allowZeroPrice' section below.

    Additional information is not required, but can optionally be set when
    adding a stock transaction:

    Optional: commission

        $sa->stockTransaction({
            ...
            commission      => 8.95,
            ...
        });

    Optional: regulatoryFees

    In the United States the Securities and Exchange Commission imposes
    regulatory fees on stock brokers or dealers. Instead of paying these
    with their profits, these for-profit companies often pass these fees on
    to their customers directly. The regulatoryFees property could be used
    for similar purposes in other jurisdictions.

    See http://www.sec.gov/answers/sec31.htm for more information.

        $sa->stockTransaction({
            ...
            regulatoryFees  => 0.04,
            ...
        });

    Optional: otherFees

    Any other fees that your jurisdiction, exchange, or broker adds in
    addition to commission and regulatory fees.

        $sa->stockTransaction({
            ...
            otherFees       => 8.95,
            ...
        });

 profit

    Returns the numeric total profit (or loss) for all realizations in the
    stock account.

        my $profit = $sa->profit();

 commissions

    Returns the numeric total commissions paid on all included
    transactions.

        my $commissions = $sa->commissions();

 totalCommissions

    Same as commissions above.

 maxCashInvested

    Returns the maximum cash value invested in stocks at once. Uses
    transaction dates and outlays to find this value.

        my $maxCashInvested = $sa->maxCashInvested();

 profitOverOutlays

        my $profitOverOutlays = $sa->profitOverOutlays();

    Returns the ratio of profit to outlays. In other words, the profit
    divided by the outlays.

 profitOverYears

        my $profitOverYears = $sa->profitOverYears();

    Returns the ratio of profit to years. So if you took the seconds
    between the first transaction date and the last transaction date, and
    divided by the number of seconds in a year to get time t, this returns
    profit divided by time t.

 regulatoryFees

        my $regulatoryFees = $sa->regulatoryFees();

    Returns the total of all regulatory fees paid in all transactions.

 otherFees

        my $otherFees = $sa->otherFees();

    Returns the total of all other fees paid in all transactions.

 summaryByStock

    Returns a string showing how you did for each stock. It begins with a
    header, and then a line for each stock with the following information:

        Symbol ROI Outlays Revenues Profit

    with a row of dashes between each line as a visual cue for which values
    belong together.

        print $sa->summaryByStock();

 stats

    Returns a reference to an array of statistics. Every other position,
    starting with zero, contains the name of the value stored at the next
    position. Here is each name prefixed by its location index:

         0  startDate
         2  endDate
         4  maxCashInvested
         6  totalOutlays
         8  totalRevenues
        10  profit
        12  profitOverYears
        14  profitOverOutlays
        16  profitOverMaxCashInvested
        18  pomciOverYears
        20  commissions
        22  regulatoryFees
        24  otherFees
        26  numberOfTrades
        28  numberExcluded

    where "pomci" is short for "Profit Over Max Cash Invested". As shown
    above, there is an $sa->profit() method. But if you wished to get the
    profit from stats instead, you could. Perl arrays are zero-indexed, and
    each of the above names is followed by the value, so to get the profit
    name and value:

        my $stats = $sa->stats();
        my $profitIndex = 10;
        my $profitName = $stats->[$profitIndex];
        my $profitValue = $stats->[$profitIndex+1];

    Of course all that seems like a lot of work compared to calling
    $sa->profit(). But if for some reason you want to grab all the stats in
    one go in a reference and process them somehow, stats is the method for
    you.

    If you are doing much of this work, I suggest looking at the code I've
    implemented in StockAccount.pm for methods stats() and statsString(),
    which might provide you with some useful guides for how to more
    conveniently access and traverse such information. For example:

        for (my $x=0; $x<scalar(@$statsLinesArray); $x+=3) {
            my ($name, $key, $valPattern) = @$statsLinesArray[$x .. $x+2];
            $statsString .= sprintf("%30s $valPattern\n", $name, $stats->{$key});
        }

    You have access to the $statsLinesArray structure through the method of
    the same name:

        my $statsLinesArray = $sa->statsLinesArray();

    In version 0.01, it looked something like this:

        my $statsLinesArray = [
            'First Trade Date'                  => 'startDate'                  => '%35s',
            'Last Trade Date'                   => 'endDate'                    => '%35s',
            'Maximum Cash Invested at Once'     => 'maxCashInvested'            => '%35.2f',
            'Sum Outlays'                       => 'totalOutlays'               => '%35.2f',
            'Sum Revenues'                      => 'totalRevenues'              => '%35.2f',
            'Total Profit'                      => 'profit'                     => '%35.2f',
            'Profit Over Years'                 => 'profitOverYears'            => '%35.2f',
            'Profit Over Sum Outlays'           => 'profitOverOutlays'          => '%35.2f',
            'Profit Over Max Cash Invested'     => 'profitOverMaxCashInvested'  => '%35.2f',
            'The Above (^) Over Years'          => 'pomciOverYears'             => '%35.2f',
            'Total Commissions'                 => 'commissions'                => '%35.2f',
            'Total Regulatory Fees'             => 'regulatoryFees'             => '%35.2f',
            'Total Other Fees'                  => 'otherFees'                  => '%35.2f',
            'Num Trades Included in Stats'      => 'numberOfTrades'             => '%35d',
            'Num Trades Excluded from Stats'    => 'numberExcluded'             => '%35d',
        ];

    I imagine this structure may change in future versions.

 statsString

    Many users will likely just want to print out the stats for display
    instead of looping through the values. This method loops through them
    all and creates readable formatted text you can print.

        print $sa->statsString();

    Note that it's only formatted up to a point. I did not add a currency
    notation or do much formatting on the numbers. This is partly because I
    don't know what currency you're using, and partly because there are
    good modules already written to format currency and numbers. It is a
    job best left to modules designed specifically for those purposes, such
    as Number::Format, and I suggest you grab values using other
    Finance::StockAccount methods and use such modules if you need good
    currency symbol and number formatting.

 statsForPeriod

    This method returns a reference to a hash of account statistics for an
    arbitrary date range you provide. The return value takes the following
    form:

        {
            totalOutlays                => $totalOutlays,
            totalRevenues               => $totalRevenues,
            maxCashInvested             => $maxCashInvested,
            profit                      => $profit,
            profitOverOutlays           => $profit / $totalOutlays,
            profitOverMaxCashInvested   => $profit / $maxCashInvested,
            commissions                 => $commissions,
            regulatoryFees              => $regulatoryFees,
            otherFees                   => $otherFees,
            numberOfTrades              => $transactionCount,
        }

    The date range must be provided as two Time::Moment objects:

        my $statsForPeriod = $sa->statsForPeriod($tm1, $tm2);

    where $tm2 should represent a time that came after $tm1. Time::Moment
    provides several methods instantiating new objects with date/time
    information. When doing so by hand, I find the most convenient one is
    usually the Time::Moment->from_string method:

        # Create a new Time::Moment object for 2:00 PM, January 31, 2014 GMT
        my $tm1 = Time::Moment->from_string("20140131T140000Z")

    Please see Time::Moment's documentation for more information.

 annualStats

    This method basically returns a reference to an array of
    "statsForPeriod" hashes above, one for each year in chronological
    order.

 annualStatsString

    Iterates through annualStats and returns a string of information in
    columns and rows. It looks something like this:

              Year      Outlays     Revenues  MaxInvested       Profit OverOut OverInvested   Commiss RegFees OthFees NumTrades
              2012     14454.48     15219.04     15989.18       764.56    0.05         0.05    229.99    0.37    0.00        80
              2013     59995.61     65866.67     16421.24      5871.07    0.10         0.36    508.56    1.27    0.00       116
              2014     28838.24     32162.69     12364.62      3324.46    0.12         0.27    237.51    0.75    0.00        73
        ------------------------------------------------------------------------------------------------------------------------
        COL SUMS      103288.33    113248.41     44775.05      9960.08    0.27         0.67    976.05    2.38    0.00       269
        ------------------------------------------------------------------------------------------------------------------------
        ACCT TOTAL    103288.34    113248.42     15989.18      9960.08    0.10         0.62    976.05    2.38    0.00       130

    The columns explained further:

    - Outlays - acquisition costs, including commissions and fees

    - Revenues - divestment gains, reduced by commissions and fees

    - Maximum Cash Invested - total acquisition cost at the moment of
    maximum simultaneous unrealized investment. Put another way: the most
    cash you had invested in stocks at once.

    - Total Profit - revenues less outlays

    - Profit Over Outlays - profit divided by outlays

    - Profit Over Max Cash Invested - profit divided by max cash invested

    - Total Commissions

    - Total Regulatory Fees

    - Total Other Fees

    - Num Trades - number of trades examined that contributed to these
    stats values

    In COL SUMS row, the columns are summed (even for columns where that
    doesn't make much sense), and then in the ACCT TOTAL row, total account
    statistics are presented.

    Notice how "off" the NumTrades values look when summed compared to the
    account total. This is because it counts the trades in all realizations
    that overlap the time period, so many trades are counted twice. See
    "Why does that number look wrong?" above.

 quarterlyStats

    Like annualStats but per quarter. Here a quarter is defined by dividing
    up the year into four three-month periods, starting in January and
    ending in December.

 quarterlyStatsString

    Like annualStatsString but for quarter.

 monthlyStats

    Like annualStats but per month.

 monthlyStatsString

    Like annualStatsString but per month.

 getSet

        my $set = $sa->getSet($hashKey);

    Returns the Finance::StockAccount::Set object specified by $hashKey, or
    undef if not found.

    If you want to get into the details of the accounting for a particular
    set, accessing the set is the way to go. You can retrieve the set using
    a hashKey made up of the stock symbol and exchange in the form:

        symbol:exchange

    So for example, if I added stock transactions for Apple stock using the
    symbol AAPL and the exchange NASDAQ, my hashKey would be

        AAPL:NASDAQ

    The set can be returned with the getSet method passing in the hashKey
    as a string:

        my $appleSet = $sa->getSet('AAPL:NASDAQ');

    If you didn't set an exchange, which is optional for stock objects,
    just use the symbol:

        my $appleSet = $sa->getSet('AAPL');

    That will give you a Finance::StockAccount::Set object.
    Finance::StockAccount::Set is installed with the Finance::StockAccount
    module. To learn more about sets, run

        perldoc Finance::StockAccount::Set

    from the command line.

 getSetFiltered

        my $set = $sa->getSetFiltered($hashKey);

    Same as getSet except it filters out all sets that are ruled out by
    skipStocks (see skipStocks method below) or for which there are no
    realizations -- no pairings of acquisition and divestment. Returns
    undef if no set is found matching the hashKey, containing realizations,
    and not on the skipStocks list.

 getFilteredSets

        my $sets = $sa->getFilteredSets();

    Returns a reference to the array of all sets in the account that match
    the getSetFiltered criteria above.

 realizationsString

        print $sa->realizationsString();

    If you want to get even further down into the weeds than
    Finance::StockAccount::Set objects, you can look at
    Finance::StockAccount::Realization objects. Sets are made up of them,
    so you can access them through the Set object. But for a quick
    overview/printout, you can use this method to retrieve a string showing
    each realization. The method loops through each set, and each
    realization within the set, retrieving a string for each one that is
    combined into the return value.

 availableAcquisitionsString

        print $sa->availableAcquisitionsString('WFM');

    Returns the string showing all acquisitions not yet paired with a
    divestment, which one could use to evaluate cost basis for a potential
    sale or cover. With $hashKey passed in, it will be limited to the Set
    object matching $hashKey (a string in the form '<symbol>:<exchange>',
    e.g. 'TWTR:NYSE', or just '<symbol>', e.g. 'TWTR', if no exchange was
    specified on the stock).

    With no arguments, loops through all sets and aggregates the data into
    one string.

 skipStocks

    After adding a bunch of transactions, or importing an entire account
    history, you may wish to exclude certain stocks from calculations, at
    least temporarily. You can do this using the skipStocks method. Pass it
    a string list of the stock symbols you would like to skip. If the
    optional exchange parameter was set, you must join the exchange string
    to the symbol string with a colon. For example:

        $sa->skipStocks(qw(AMD TWTR:NYSE));
        my $profit = $sa->profit();
        ...

    Now any calculations, such as profit, will exclude the stock specified
    as symbol => 'AMD' with no exchange, and the stock specified as symbol
    => 'TWTR', exchange => 'NYSE'.

    New calls to the method are additive, so you can add skip stocks one at
    a time or all at once or anywhere in between.

    If you'd like to see the current set of skipStocks, you can call the
    method with no arguments and it will return an alphabetically sorted
    list of strings:

        print join(', ', $sa->skipStocks()), "\n"; # prints "AMD, TWTR:NYSE\n"

    If there are no skip stocks to return, it will return undef.

 resetSkipStocks

    Use this method to reset the skipStocks list to an empty list.

 allowZeroPrice

    Transactions where the price is zero are treated as suspect by default,
    and stockTransaction will not add them to the StockAccount object.
    However, there are some legitimate use cases where one might want them
    to be included, so you can set the allowZeroPrice option on the
    StockAccount object to do that:

        $sa->allowZeroPrice(1); # allow transactions with price == 0
        $sa->allowZeroPrice(0); # disallow transactions with price == 0

    or check the value with the same method and no arguments:

        if ($sa->allowZeroPrice()) {
            ... do something ...
        }

    As mentioned above, it can also be set using the new method, described
    above.

INSTALLATION

    A classic and still great means of installing a Perl module is
    basically as follows. Download the tarball, extract it somewhere, and
    then in that directory run these commands:

        perl Makefile.PL
        make
        make test
        make install

    Of course there are lots of options and alternatives. For example, say
    you were on unix or linux and you created a "plib" directory in your
    home directory and configured Perl to look there, and you wanted to
    install there instead. You could change that first line to do that:

        perl Makefile.PL INSTALL_BASE=~/plib

    And there are lots of other things you can do. I recommend looking at

        perldoc ExtUtils::MakeMaker

    (or just view it on cpan or metacpan) for more information.

    Also, there are several tools for installing Perl modules, such as
    cpanm. Many of them will install dependencies for you. I did not test
    my distribution with all such tools, so please let me know if you have
    problems installing this module with any of them.

    This is by no means meant as an authoritative guide for how to install
    Perl modules: there is a lot of good material on that subject online
    and in perldoc pages, so please look for those sources.

MORE EXAMPLES

    If you download this module as a tarball from cpan or metacpan and
    extract it somewhere, you should see a

        t/

    directory. In there are tests written for this module, providing more
    examples of code that makes use of this module. Note that much of this
    code was written specifically to test features and methods of this
    module, and may not represent typical or ideal usage. Note that several
    of these tests require the files in

        t/data/

    to work.

AUTHOR

    John Everett Refior, <jrefior at gmail.com>

BUGS

    Please report any bugs or feature requests to bug-finance-stockaccount
    at rt.cpan.org, or through the web interface at
    http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Finance-StockAccount. I
    will be notified, and then you'll automatically be notified of progress
    on your bug as I make changes.

SUPPORT

    You can find documentation for this module with the perldoc command.

        perldoc Finance::StockAccount

    You can also look for information at:

      * RT: CPAN's request tracker (report bugs here)

      http://rt.cpan.org/NoAuth/Bugs.html?Dist=Finance-StockAccount

      * AnnoCPAN: Annotated CPAN documentation

      http://annocpan.org/dist/Finance-StockAccount

      * CPAN Ratings

      http://cpanratings.perl.org/d/Finance-StockAccount

      * Search CPAN

      http://search.cpan.org/dist/Finance-StockAccount/

ACKNOWLEDGEMENTS

    I would like to thank the Perl Monks for contributing their wisdom when
    I posted questions about how to handle date/time and whether there was
    already a module capable of doing what I planned.

LICENSE AND COPYRIGHT

    Copyright 2014 John Everett Refior.

    This program is free software; you can redistribute it and/or modify it
    under the terms of the the Artistic License (2.0). You may obtain a
    copy of the full license at:

    http://www.perlfoundation.org/artistic_license_2_0

    Any use, modification, and distribution of the Standard or Modified
    Versions is governed by this Artistic License. By using, modifying or
    distributing the Package, you accept this license. Do not use, modify,
    or distribute the Package, if you do not accept this license.

    If your Modified Version has been derived from a Modified Version made
    by someone other than you, you are nevertheless required to ensure that
    your Modified Version complies with the requirements of this license.

    This license does not grant you the right to use any trademark, service
    mark, tradename, or logo of the Copyright Holder.

    This license includes the non-exclusive, worldwide, free-of-charge
    patent license to make, have made, use, offer to sell, sell, import and
    otherwise transfer the Package with respect to any patent claims
    licensable by the Copyright Holder that are necessarily infringed by
    the Package. If you institute patent litigation (including a
    cross-claim or counterclaim) against any party alleging that the
    Package constitutes direct or contributory patent infringement, then
    this Artistic License to you shall terminate on the date that such
    litigation is filed.

    Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER
    AND CONTRIBUTORS "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES.
    THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
    PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY
    YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR
    CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR
    CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE,
    EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.