---
description: >-
  Creating Your Portfolio Position in a Very Simple Way: Embracing a Bias-Free
  Approach
---

# AM (Alpha Model)

## Develop AM (Alpha Model)

### Helper Function: Calculating Previous Start Date

```python
from datetime import datetime, timedelta


def calculate_previous_start_date(start_date, lookback_days):
    start = datetime.strptime(str(start_date), "%Y%m%d")
    previous_start = start - timedelta(days=lookback_days)
    return int(previous_start.strftime("%Y%m%d"))
```

### Very simple AM script

```python
from finter import BaseAlpha


# Define the lookback period in days
LOOKBACK_DAYS = 365

start, end = 20200101, 20220101

# Alpha class inheriting from BaseAlpha
class Alpha(BaseAlpha):
    # Method to generate alpha
    def get(self, start, end):
        # Calculate the start date for data retrieval
        pre_start = calculate_previous_start_date(start, LOOKBACK_DAYS)
        
        
        # Retrieve daily closing prices
        self.close = self.get_cm(
            "content.fnguide.ftp.price_volume.price_close.1d"
        ).get_df(pre_start, end)
        # Calculate momentum
        momentum_21d = self.close.pct_change(21)
        # Rank stocks by momentum
        stock_rank = momentum_21d.rank(pct=True, axis=1)
        # Select top 10% of stocks
        stock_top10 = stock_rank[stock_rank>=0.9]
        # Apply rolling mean to smooth data
        stock_top10_rolling = stock_top10.rolling(21).apply(lambda x: x.mean())
        # Normalize and scale to position sizes
        stock_ratio = stock_top10_rolling.div(stock_top10_rolling.sum(axis=1), axis=0)
        
        
        position = stock_ratio * 1e8
        # Shift positions to avoid look-ahead bias
        alpha = position.shift(1)
        # Alpha position must be a value between start and end
        return alpha.loc[str(start): str(end)]

# Run the alpha generation process
alpha = Alpha().get(start, end)
```

***

<details>

<summary>Detail code description.</summary>

### Alpha Class Definition

```python
LOOKBACK_DAYS = 365
class Alpha(BaseAlpha):
```

We define a constant `LOOKBACK_DAYS` set to 365, representing one year of historical data. The `Alpha` class inherits from `BaseAlpha`, which contains methods and properties useful for alpha development.

### Alpha Generation Method

```python
    def get(self, start, end):
        pre_start = calculate_previous_start_date(start, LOOKBACK_DAYS)
```

The `get` method is the core function that generates the alpha. It takes a start and end date for the analysis period. The `calculate_previous_start_date` function is used to extend the start date further back by the number of `LOOKBACK_DAYS`.

### Data Retrieval

```python
        # Retrieve daily closing prices for the specified date range
        self.close = self.get_cm(
            "content.fnguide.ftp.price_volume.price_close.1d"
        ).get_df(pre_start, end)
```

This line retrieves the daily closing prices of stocks between the `pre_start` and `end` dates. The `get_cm` method is a part of the `BaseAlpha` class and is used to call data modules.

### Momentum Calculation

```python
        # Calculate 21-day momentum for closing prices
        momentum_21d = self.close.pct_change(21)
```

We calculate the 21-day momentum of the closing prices, which is the percentage change over the last 21 days.

### Stock Ranking

```python
        # Rank stocks based on their momentum
        stock_rank = momentum_21d.rank(pct=True, axis=1)
```

The momentum values are then ranked on a percentile scale (0 to 1) across all stocks for each day.

### Selecting Top 10% Stocks

```python
        # Filter to select the top 10% of stocks by momentum
        stock_top10 = stock_rank[stock_rank>=0.9]
```

We filter the stocks to select only the top 10% based on their momentum ranks.

### Rolling Mean of Top Stocks

```python
        # Apply a rolling mean to smooth the top stocks' data
        stock_top10_rolling = stock_top10.rolling(21).apply(lambda x: x.mean())
```

A rolling mean with a 21-day window is applied to the top 10% stocks to smooth out the data.

### Position Sizing

```python
        # Normalize the rolling mean values and scale to position sizes
        stock_ratio = stock_top10_rolling.div(stock_top10_rolling.sum(axis=1), axis=0)
        position = stock_ratio * 1e8
```

The rolling mean values are normalized by dividing by the sum across all stocks to get a ratio. This ratio is then scaled up to determine the position sizes, here represented by a hypothetical amount of 100 million (1e8).

### Generating Alpha

```python
        # Shift positions to avoid look-ahead bias and generate the alpha
        alpha = position.shift(1)
        # Alpha position must be a value between start and end
        return alpha.loc[str(start): str(end)]
```

The final alpha is generated by shifting the positions by one day to avoid look-ahead bias. This means we use yesterday's positions to determine today's trades.

### Running the Alpha

```python
# Create an instance of the Alpha class and run the alpha generation
alpha = Alpha().get(20230101, 20230201)
```

Finally, we create an instance of the `Alpha` class and call the `get` method with a specific start and end date to run the alpha generation process.

</details>

{% hint style="danger" %}
This guide provides a basic framework for writing an alpha in Python. It is important to note that this is a simplified example, and real-world alpha development involves more complex data analysis, risk management, and performance evaluation.
{% endhint %}
