Create quantile slices from dataframe columns
To answer your questions in order:


Yes: your code could be optimised by calculating .count() (with respect to each slice of pntls) only once per outer loop, instead of n + 1 times (where n is the value of .count()) as per your current implementation. In the full example below, I show how you can use pandas.qcut to make this much more efficient in the add_quantiles function.
Re-using calculations is more efficient, but a procedure that doesn't alter the dataframe is more flexible: in the exmaple below, the calculations are re-used, but the main dataset isn't changed (everything is done from a copy). This may not be desiarable if: (a) you don't intend on using this code for any other purpose (or for more than one use, where keeping the original dataset untouched means you can re-run the procedure), or (b) if the size of the data in memory is large.
It could be improved: if I have understood corretly, the results of calculating col_slice in the inner most loop is actually used hld_per number of times (except when the column being passed to col_slice is within hld_per columns from the end of the dataset). We can reduce the number of calculations of col_slice by a factor of hld_per, therefore, if we re-use the results. In the example I've given below, I show how you can do this to improve performance.
Only if you don't know your data structure ahead of time; you've used indexing by position rather than label to good effect.
Apart from the points above: your code was easy to read (thanks, too, for the detailed question!)!


My suggested re-write using the above suggestions is given below. The main function to run is create_csvs (nb: this uses label indexing instead of the positional indexes that you use - this could be switch out if you prefer). This will create csv files in the same format as your example code.

NB: I have assumed that the order of the rows in each column of the output CSVs doesn't matter. If this does matter, I can suggest a change.

    from collections import defaultdict

    colname = lambda col, suffix: '{}_{}'.format(suffix, col)

    def add_quantiles(data, columns, suffix, quantiles=4, labels=None):
        """ For each column name in columns, create a new categorical column with
            the same name as colum, with the suffix specified added, that
            specifies the quantile of the row in the original column using
            pandas.qcut().

            Input
            _____
            data:
                pandas dataframe
            columns:
                list of column names in `data` for which this function is to create
                quantiles
            suffix:
                string suffix for new column names ({`suffix`}_{collumn_name})
            labels:
                list of labels for each quantile (should have length equal to `quantiles`)

            Output
            ______
            pandas dataframe containing original columns, plus new columns with quantile
            information for specified columns.
        """
        d = data.copy()
        quantile_labels = labels or [
            '{:.0f}%'.format(i*100/quantiles) for i in range(1, quantiles+1)
        ]
        for column in columns:
            d[colname(column, suffix)] = pd.qcut(d[column], quantiles, labels=quantile_labels)
        return d


    def create_csvs(data, columns, hld_per=3, quantiles=4, suffix='quant'):
        """
            Input
            _____
            data:
                the full dataset
            columns:
                the ordered list of names of the date columns
            hld_per:
                holding period
            suffix:
                string suffix for quantile columns (no effect on output)
            quantiles:
                number of quantiles

            Output
            ______
            None

            Effect
            ______
            writes csv files
        """
        quantile_labels = ['{:.0f}%'.format(i*100/quantiles) for i in range(1, quantiles+1)]
        d = add_quantiles(data, columns, suffix, quantiles, quantile_labels)

        period_dict = lambda: defaultdict(list)
        ports = defaultdict(period_dict)
        for i in range(len(columns) - hld_per + 1):
            column = columns[i]
            period_columns = columns[max(i-hld_per, 0):i+1]
            for label in quantile_labels:
                for period in period_columns:
                    ports[label][period] += list(d[column][d[colname(column, suffix)] == label].values)

        for i, label in enumerate(quantile_labels):
            # Fill each list in `ports` with `np.null` so that they all have the same length of `maxlen`
            max_len = max(map(lambda v: len(v[1]), ports[label].items()))
            for c in ports[label]:
                ports[label][c] += [np.NaN]*(max_len-len(ports[label][c]))
            pd.DataFrame(ports[label]).to_csv("portstst2_" + str(i+1) + ".csv", sep=',', index=False, header=True)