REF: Separate window bounds calculation from aggregation functions
State: closed

- [x] tests added / passed
- [x] passes `black pandas`
- [x] passes `git diff upstream/master -u -- "*.py" | flake8 --diff`

Pre-req for https://github.com/pandas-dev/pandas/issues/28987

Currently many of the aggregation functions in `window.pyx` follow the form:

```
def roll_func(values, window, minp, N, closed):
    # calculate window bounds _and_ validate arguments
    start, end, ... = get_window_bounds(values, window, minp, N, ...)
    for i in range(values):
        s = start[i]
        ....
```

This PR refactors out the window bound calculation into `window_indexer.pyx` and validation so the aggregation functions can be of the form:

```
def roll_func(values, start, end, minp):
    for i in range(values):
        s = start[i]
        ....
```

The methods therefore in `rolling.py` now have the following pattern:

1. Fetch the correct cython aggregation function (whether the window is fixed or variable), and prep it with kwargs if needed
2. Compute the `start` and `end` window bounds from functionality in `window_indexer.pyx`
3. Pass in the `values`, `start`, `end`, `min periods` into the aggregation function.

Labels:
name: Refactor
description: Internal refactoring of code
name: Window
description: rolling, ewma, expanding

Comments:
are there more window/rolling-centric .pyx files on the horizon?  if so, would it make sense to make a _libs/window/ directory?
@jbrockmendel Should just be `window.pyx` and `window_indexer.pyx` for now, but I think those two files are enough to split into their own directory as you suggested. Will tackle that reorg step once I get all the tests passing.
sounds good.  I think skiplist may belong in there too.

If the intra-pandas dependencies of _libs/windows/ can be tighted locked down (e.g. "only _libs.util") thatd be great
Side-note: is there a reason not to de-duplicate _Window._apply and EWM._apply?  They look really similar
not easy to tell from the CI log whats going wrong.  does this pass locally?
> Side-note: is there a reason not to de-duplicate _Window._apply and EWM._apply?
Probably not. I can try to dedupe in this PR

Ya not all the test cases are handled yet. `groupby.rolling.apply` does a lot is dispatching so the tracebacks are the clearest.
motivated by [comment](https://github.com/pandas-dev/pandas/issues/28987#issuecomment-553145325) from @rgommers: can we think of this as something that is worthwhile independent of the numba decision?
@jbrockmendel this has been a larger undertaking than I expected, but I think at minimum it's a nice refactor to make the function signatures on the python and cython side more consistent and centralizing more of the prep logic around `min_periods` and such. 

I expect the subsequent PR's to be less of a hassle, but this refactor will help make the Numba integration more straightforward IMO.
Thanks for the review @jreback. I'll address them once all the tests are passing.

Will say debugging the tests would be a lot easier if the Cython parts were written in Numba :) 
@jreback @jbrockmendel tests are passing locally now. Since this PR is already bulky, the follow up PR will be

1) Create a new `pandas/_libs/window` directory with `indexers.pyx` and `aggregations.pyx`
2) Add BaseIndexer base class and make it passable as a window.
Happy to defer to others here. Things seem nice based on a quick skim.