Add rolling window to sklearn.model_selection.TimeSeriesSplit

### Describe the workflow you want to enable

I wanted to ask whether any plans exist to implement a rolling/sliding window method in the TimeSeriesSplit class:

![68747470733a2f2f692e6962622e636f2f4b576b665137712f6e6577706c6f742e706e67](https://user-images.githubusercontent.com/28893120/154545460-d1629e8a-22a4-494d-affc-2df3cb95ade7.png)

 Currently, we are limited to using the expanding window type. For many financial time series models where a feature experiences a structural break, having a model whose weights are trained on the entire history can prove suboptimal.

I noted in https://github.com/scikit-learn/scikit-learn/pull/13204, specifically svenstehle's comments, that this might be on the horizon? 

### Describe your proposed solution

Current Implementation

```
>>> x = np.arange(15)
>>> cv = TimeSeriesSplit(n_splits=3, gap=2)
>>> for train_index, test_index in cv.split(x):
...      print("TRAIN:", train_index, "TEST:", test_index)
TRAIN: [0 1 2 3] TEST: [6 7 8]
TRAIN: [0 1 2 3 4 5 6] TEST: [ 9 10 11]
TRAIN: [0 1 2 3 4 5 6 7 8 9] TEST: [12 13 14]
```

Desired outcome

```
>>> x = np.arange(10)
>>> cv = TimeSeriesSplit(n_splits='walk_fw',  max_train_size=3, max_test_size=1)
>>> for train_index, test_index in cv.split(x):
...      print("TRAIN:", train_index, "TEST:", test_index)
TRAIN: [0 1 2] TEST: [3]
TRAIN: [1 2 3] TEST: [ 4]
TRAIN: [2 3 4] TEST: [5]
TRAIN: [ 3 4 5] TEST: [6]
TRAIN: [ 4 5 6] TEST: [7]
TRAIN: [ 5 6 7] TEST: [8]
TRAIN: [ 6 7 8] TEST: [9]
```

Where the 'stride' of the walk forward is proportionate to the test set, or walks by the max_train_size parameter?



### Describe alternatives you've considered, if relevant

_No response_

### Additional context

_No response_

COMMENT:
To add the `rolling window` method, we don't need to set the `train_size` as an input. The code can handle it if written properly. I was working on it for my own project; this is what I made to support both the `expanding` and `rolling` windows. I can create a PR if agreed.

```
from sklearn.model_selection._split import _BaseKFold
from sklearn.utils import indexable
from sklearn.utils.validation import _num_samples
import numpy as np

class TimeSeriesSplit(_BaseKFold):

    def __init__(self, n_splits=5, *, max_train_size=None, test_size=None, gap=0, window_method='expanding'):
        super().__init__(n_splits, shuffle=False, random_state=None)
        self.max_train_size = max_train_size
        self.test_size = test_size
        self.gap = gap
        self.window_method = window_method

    def split(self, X, y=None, groups=None):
        X, y, groups = indexable(X, y, groups)
        n_samples = _num_samples(X)
        n_splits = self.n_splits
        n_folds = n_splits + 1
        gap = self.gap
        test_size = (
            self.test_size if self.test_size is not None else n_samples // n_folds
        )

        # Make sure we have enough samples for the given split parameters
        if n_folds > n_samples:
            raise ValueError(
                f"Cannot have number of folds={n_folds} greater"
                f" than the number of samples={n_samples}."
            )
        if n_samples - gap - (test_size * n_splits) <= 0:
            raise ValueError(
                f"Too many splits={n_splits} for number of samples"
                f"={n_samples} with test_size={test_size} and gap={gap}."
            )
        
        if self.window_method not in ['expanding', 'rolling']:
            raise ValueError(f"Unsupported window method: {self.window_method}")
        
        
        indices = np.arange(n_samples)
        
        test_starts = range(n_samples - n_splits * test_size, n_samples, test_size)
        train_start = 0
        for test_start in test_starts:
            train_end = test_start - gap 
    
            if self.max_train_size and self.max_train_size < train_end:
                yield (
                    indices[train_end - self.max_train_size : train_end],
                    indices[test_start : test_start + test_size],
                )
            else:
                yield (
                    indices[train_start : train_end],
                    indices[test_start : test_start + test_size],
                )
           
            if self.window_method == 'rolling':
                train_start += test_size

```

Labels: New Feature, module:model_selection