# Dynamic Pricing for Bulk Coretime Sales

**URL:** <https://forum.polkadot.network/t/dynamic-pricing-for-bulk-coretime-sales/3359>\
**Category:** Tech Talk\
**Created:** [July 8, 2023, 2:07pm UTC](https://forum.polkadot.network/t/dynamic-pricing-for-bulk-coretime-sales/3359 "2023-07-08T14:07:01Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![alice\_und\_bob](https://dub1.discourse-cdn.com/flex005/user_avatar/forum.polkadot.network/alice_und_bob/32/10098_2.png) [@alice\_und\_bob](https://forum.polkadot.network/u/alice_und_bob)\
**Post date:** [July 8, 2023, 2:07pm UTC](https://forum.polkadot.network/t/dynamic-pricing-for-bulk-coretime-sales/3359/1 "2023-07-08T14:07:01Z")

</div>

_This post proposes a dynamic pricing mechanism based on a power function. The function is constructed so the price stays fairly stable around a governance-controlled target number of cores sold in the previous period, and scales down to a minimum price or maximum price increase factor as it deviates from the target._

 ![0006-baseline](https://europe1.discourse-cdn.com/flex005/uploads/polkadot2/original/2X/0/073dc9b227acf45b00e5c034e3b393c4060837b3.png)

# Gavin Wood’s proposal

RFC-1, currently live as a pull request [here](https://github.com/polkadot-fellows/RFCs/pull/1/files), proposes the sale of bulk coretime on a 4-weekly basis.

According to RFC-1, pricing should be dynamic and change every sale period based on the price and demand of the previous period. RFC-1 defines the mechanism to set the price as out of the scope of the proposal.

RFC-1 notes:

> ### Notes on Price Setting
> 
> The specific price setting mechanism is out of scope for this proposal and should be covered in some other work. The present proposal assumes the existence of a price-setting mechanism which could take into account three parameters; two mostly fixed and one which changes each `BULK_PERIOD`. These parameters are `BULK_TARGET`, `BULK_LIMIT` and `CORES_SOLD` which is the actual number of cores sold for the present `BULK_PERIOD` and is always an unsigned integer at most `BULK_LIMIT`.
> 
> In general we would expect the price to increase the closer `CORES_SOLD` gets to `BULK_LIMIT` and to decrease the closer it gets to zero. If it is exactly equal to `BULK_TARGET`, then we would expect the price to remain the same.
> 
> A simple example of this would be the formula:
> 
> ```auto
> NEW_PRICE := IF CORES_SOLD < BULK_TARGET THEN
> OLD_PRICE - OLD_PRICE / 2 * CORES_SOLD / BULK_TARGET
> ELSE
> OLD_PRICE + OLD_PRICE / 2 *
> (CORES_SOLD - BULK_TARGET) / (BULK_LIMIT - BULK_TARGET)
> END IF
> 
> ```
> 
> This exists only as a trivial example to demonstrate a basic solution exists, and should not be intended as a concrete proposal.

The intended function looks like this:

 ![image](https://europe1.discourse-cdn.com/flex005/uploads/polkadot2/original/2X/b/b4c7ef2c24a9f9acb5f625793896d275e8abd9dd.png)

# Design Goals

Starting from the function given above, the following improvements are proposed:

- Left side goes to zero
- Price plateaus around the target
- Introduce a max price increase factor

# Details

## Left side goes to zero

The left side of the function only goes to OLD\_PRICE / 2. In conditions of rapid price changes on the market, this might lead to a period of one or a few months where the price does not adapt quickly enough to changing markets. It is proposed to allow the left side of the function to go close to 0 if cores sold go to 0. The rationale is that if there are actually 0 cores sold, something about the previous sale price was fundamentally wrong and the price needs to adapt quickly.

We introduce MIN\_PRICE as a new variable.

## Price plateaus around BULK\_TARGET

If the number of cores is close to BULK\_TARGET, less extreme price changes might be sensible. This ensures that a drop in sold cores or an increase doesn’t lead to immediate price changes, but rather slowly adapts. Only if more extreme changes in the number of sold cores occur, does the price slope increase.

We introduce SCALE\_DOWN and SCALE\_UP to control for the steepness of the left and the right side of the function respectively.

## Introduce a max price increase factor

Introducing this lever gives governance an additional control lever and avoids the necessity for a future runtime upgrade.

We introduce MAX\_PRICE\_INCREASE\_FACTOR as a factor of what the price may increase from one period to another.

# Function

## Parameters

We assume these parameters from RFC-1:

- `BULK_LIMIT` - the maximum number of cores being sold
- `BULK_TARGET` - the target number of cores being sold
- `CORES_SOLD` - the number of cores being sold
- `OLD_PRICE` - the price of a core in the previous period

And additionally, introduce:

- `MIN_PRICE` - the minimum price a core will always cost. MIN\_PRICE \>= 0
- `MAX_PRICE_INCREASE_FACTOR` - the factor by which the price maximally can change from one period to another. MAX\_PRICE\_INCREASE\_FACTOR \> 1
- `SCALE_DOWN` - the steepness of the left side of the function. Should be \>= 1
- `SCALE_UP` - the steepness of the right side of the function. Should be \>= 1

## CODE

in Python

```auto
    if CORES_SOLD <= BULK_TARGET:
        return (OLD_PRICE - MIN_PRICE) * (1 - (abs(CORES_SOLD - BULK_TARGET) **SCALE_DOWN / BULK_TARGET** SCALE_DOWN)) + MIN_PRICE
    else:
        return ((MAX_PRICE_INCREASE_FACTOR - 1) * OLD_PRICE * ((CORES_SOLD - BULK_TARGET)**SCALE_UP / (BULK_LIMIT - BULK_TARGET)**SCALE_UP)) + OLD_PRICE

```

## Examples

### Basic Proposal

This example proposes that the minimum price of a core is 1 DOT, the price can grow a maximum of 50% every 4 weeks and we want to dampen price change around BULK\_TARGET slightly.

```auto
BULK_TARGET = 30
BULK_LIMIT = 45
MIN_PRICE = 1
MAX_PRICE_INCREASE_FACTOR = 2
SCALE_DOWN = 2
SCALE_UP = 2
old_price = 1000

```

We get

 ![0006-baseline](https://europe1.discourse-cdn.com/flex005/uploads/polkadot2/original/2X/0/073dc9b227acf45b00e5c034e3b393c4060837b3.png)

### More aggressive pricing

We might want to have a more aggressive price growth, allowing the price to double every 4 weeks and have a linear increase in price if more than BULK\_TARGET cores are sold.

```auto
BULK_TARGET = 30
BULK_LIMIT = 45
MIN_PRICE = 1
MAX_PRICE_INCREASE_FACTOR = 2
SCALE_DOWN = 2
SCALE_UP = 1
old_price = 1000

```

 ![0006-aggressive-pricing](https://europe1.discourse-cdn.com/flex005/uploads/polkadot2/original/2X/1/12dec783c61a8368510d61f77226f25e7cc09ca3.png)

### Conservative pricing to ensure quick corrections in a bull market

If governance considers the risk that a sudden surge in DOT price might price chains out from bulk coretime markets, it can ensure the model quickly reacts to a quick drop in demand, by setting 0 \< SCALE\_DOWN \< 1 and setting the max price increase factor more conservatively.

```auto
BULK_TARGET = 30
BULK_LIMIT = 45
MIN_PRICE = 1
MAX_PRICE_INCREASE_FACTOR = 1.5
SCALE_DOWN = 0.5
SCALE_UP = 2
old_price = 1000

```

 ![0006-conservative-pricing](https://europe1.discourse-cdn.com/flex005/uploads/polkadot2/original/2X/7/7e702769fdc61d96cec7cfc762458fc9a34c78e5.png)

### Linear pricing

By setting the scaling factors to 1 and potentially adapting the max price increase, we can achieve a linear function.

```auto
BULK_TARGET = 30
BULK_LIMIT = 45
MIN_PRICE = 1
MAX_PRICE_INCREASE_FACTOR = 1.5
SCALE_DOWN = 1
SCALE_UP = 1
OLD_PRICE = 1000

```

 ![0006-linear](https://europe1.discourse-cdn.com/flex005/uploads/polkadot2/original/2X/0/0c91ee5bd5302dadc0573992a6170aa7cb6d987a.png)

# Code

A Jupyter Notebook is shared here: [Google Colab](https://colab.research.google.com/drive/15yOP6n6jfphzb9IniCWjbGHLTluwxbty?usp=sharing)

A Gist backup of the notebook is found here: [Dynamic Coretime Pricing · GitHub](https://gist.github.com/Tomen/96cdd991065cc75260948683c9fa0e13#file-gistfile1-txt)

# Future Work

I hacked together the function with my fellow pair programmer GPT-4. It’s quite possible that the mathematically inclined will find it to be confusing in its construction. I’m open to any criticism.

If this function finds acceptance, it should be tested if it is still working for different parameter sets.

This function may become part of an RFC to accompany the realization of RFC-1

# Conclusion

This proposal introduces a flexible function for dynamic coretime pricing that gives governance intuitive control levers and comes close to the proposal in RFC-1 while providing more fine-grained control of the shape of the price curve.

---

<div class="post-metadata">

**Author:** ![Sultan.dot](https://avatars.discourse-cdn.com/v4/letter/s/f1d935/32.png) [@Sultan.dot](https://forum.polkadot.network/u/Sultan.dot)\
**Post date:** [July 8, 2023, 2:26pm UTC](https://forum.polkadot.network/t/dynamic-pricing-for-bulk-coretime-sales/3359/2 "2023-07-08T14:26:12Z")

</div>

@gavofyork I think this idea is very interesting to research & learn more deeply

---

<div class="post-metadata">

**Author:** ![alice\_und\_bob](https://dub1.discourse-cdn.com/flex005/user_avatar/forum.polkadot.network/alice_und_bob/32/10098_2.png) [@alice\_und\_bob](https://forum.polkadot.network/u/alice_und_bob)\
**Post date:** [July 10, 2023, 5:14am UTC](https://forum.polkadot.network/t/dynamic-pricing-for-bulk-coretime-sales/3359/3 "2023-07-10T05:14:18Z")

</div>

This is now RFC-6

> <https://github.com/polkadot-fellows/RFCs/pull/6>
>
> RFC-1 asks for another RFC that specifies the pricing function of Bulk Coretime …Sales. RFC-6 is a proposal to apply a dynamic pricing function that has several levers for governance to adapt the pricing curve to changing market conditions.
> 
> This RFC follows a proposal in the Polkadot Forum \[here\](https://forum.polkadot.network/t/dynamic-pricing-for-bulk-coretime-sales/3359) and an invitation by Gavin Wood to submit an RFC \[here\](https://github.com/polkadot-fellows/RFCs/pull/1#issuecomment-1627626753).
