position-sizing-data 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- position_sizing_data-0.1.0/LICENSE +21 -0
- position_sizing_data-0.1.0/PKG-INFO +86 -0
- position_sizing_data-0.1.0/README.md +66 -0
- position_sizing_data-0.1.0/pyproject.toml +32 -0
- position_sizing_data-0.1.0/setup.cfg +4 -0
- position_sizing_data-0.1.0/src/position_sizing_data/__init__.py +109 -0
- position_sizing_data-0.1.0/src/position_sizing_data/data/contract-specifications.csv +132 -0
- position_sizing_data-0.1.0/src/position_sizing_data/data/drawdown-recovery.csv +13 -0
- position_sizing_data-0.1.0/src/position_sizing_data/data/losing-streak-equity.csv +21 -0
- position_sizing_data-0.1.0/src/position_sizing_data/data/pip-value-by-lot-size.csv +5 -0
- position_sizing_data-0.1.0/src/position_sizing_data.egg-info/PKG-INFO +86 -0
- position_sizing_data-0.1.0/src/position_sizing_data.egg-info/SOURCES.txt +12 -0
- position_sizing_data-0.1.0/src/position_sizing_data.egg-info/dependency_links.txt +1 -0
- position_sizing_data-0.1.0/src/position_sizing_data.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 PositionSizeTool
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: position-sizing-data
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Reference data and arithmetic for risk-based position sizing across forex, stocks and crypto futures
|
|
5
|
+
Author: JUN YI
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://positionsizetool.com/
|
|
8
|
+
Project-URL: Repository, https://github.com/tk25719/position-sizing-data
|
|
9
|
+
Project-URL: Zenodo, https://doi.org/10.5281/zenodo.22840538
|
|
10
|
+
Keywords: position sizing,risk management,forex,trading,crypto
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Financial and Insurance Industry
|
|
13
|
+
Classifier: Operating System :: OS Independent
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Topic :: Office/Business :: Financial :: Investment
|
|
16
|
+
Requires-Python: >=3.9
|
|
17
|
+
Description-Content-Type: text/markdown
|
|
18
|
+
License-File: LICENSE
|
|
19
|
+
Dynamic: license-file
|
|
20
|
+
|
|
21
|
+
# position-sizing-data
|
|
22
|
+
|
|
23
|
+
Reference data and arithmetic for risk-based position sizing across forex, stocks and crypto futures.
|
|
24
|
+
|
|
25
|
+
The same tables are published as a citable dataset: [doi:10.5281/zenodo.22840538](https://doi.org/10.5281/zenodo.22840538), and used by the web calculator at [https://positionsizetool.com/](https://positionsizetool.com/). Source repository: [https://github.com/tk25719/position-sizing-data](https://github.com/tk25719/position-sizing-data).
|
|
26
|
+
|
|
27
|
+
## Install
|
|
28
|
+
|
|
29
|
+
```console
|
|
30
|
+
pip install position-sizing-data
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## What is in it
|
|
34
|
+
|
|
35
|
+
| Function | Returns |
|
|
36
|
+
| --- | --- |
|
|
37
|
+
| `contract_specifications()` | Pip size, contract size and minimum unit step for 131 instruments, across forex pairs, metals, energies, indices, crypto futures, stocks and ETFs. |
|
|
38
|
+
| `pip_values()` | Pip value and the loss on a 20 pip move for standard, mini, micro and nano lots. |
|
|
39
|
+
| `losing_streak_equity()` | Equity remaining after 1 to 20 consecutive losses at 0.5%, 1% and 2% risk per trade. |
|
|
40
|
+
| `drawdown_recovery()` | Gain required on the reduced balance to return to the original balance, for drawdowns from 5% to 90%. |
|
|
41
|
+
| `position_size(...)` | The risk-to-units calculation itself. |
|
|
42
|
+
|
|
43
|
+
Read the tables:
|
|
44
|
+
|
|
45
|
+
```python
|
|
46
|
+
from position_sizing_data import contract_specifications
|
|
47
|
+
|
|
48
|
+
rows = contract_specifications()
|
|
49
|
+
print(rows[0])
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Compute a size:
|
|
53
|
+
|
|
54
|
+
```python
|
|
55
|
+
from position_sizing_data import position_size
|
|
56
|
+
|
|
57
|
+
result = position_size(
|
|
58
|
+
balance=10000.0,
|
|
59
|
+
risk_percent=1.0,
|
|
60
|
+
entry=1.1000,
|
|
61
|
+
stop=1.0980,
|
|
62
|
+
unit_step=1000.0, # 0.01 lot
|
|
63
|
+
)
|
|
64
|
+
print(result)
|
|
65
|
+
# {'risk_budget': 100.0, 'units': 50000.0, 'tradable_units': 50000.0, 'worst_case_loss': 100.0}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## The formula
|
|
69
|
+
|
|
70
|
+
```
|
|
71
|
+
units = (risk_budget - commission) / ((|entry - stop| + spread) x quote_rate)
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
The tradable size is that number rounded **down** to `unit_step`. `position_size` returns the worst-case loss recomputed from the rounded size, which is what the account actually loses when the stop is hit.
|
|
75
|
+
|
|
76
|
+
## Where the numbers come from
|
|
77
|
+
|
|
78
|
+
The rows in `contract_specifications()` are typical retail contract specifications, not exchange-published official values. Verify the contract size and unit step against your own broker before placing an order. The other three tables are closed-form arithmetic:
|
|
79
|
+
|
|
80
|
+
- losing streak: `remaining = (1 - risk)^n`
|
|
81
|
+
- drawdown recovery: `gain_required = 1 / (1 - drawdown) - 1`
|
|
82
|
+
- pip value: `pip_value = units x pip_size`
|
|
83
|
+
|
|
84
|
+
## Licence
|
|
85
|
+
|
|
86
|
+
MIT for the code. Data files are CC0 1.0 Universal, to the extent applicable. This is not investment advice.
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# position-sizing-data
|
|
2
|
+
|
|
3
|
+
Reference data and arithmetic for risk-based position sizing across forex, stocks and crypto futures.
|
|
4
|
+
|
|
5
|
+
The same tables are published as a citable dataset: [doi:10.5281/zenodo.22840538](https://doi.org/10.5281/zenodo.22840538), and used by the web calculator at [https://positionsizetool.com/](https://positionsizetool.com/). Source repository: [https://github.com/tk25719/position-sizing-data](https://github.com/tk25719/position-sizing-data).
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```console
|
|
10
|
+
pip install position-sizing-data
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## What is in it
|
|
14
|
+
|
|
15
|
+
| Function | Returns |
|
|
16
|
+
| --- | --- |
|
|
17
|
+
| `contract_specifications()` | Pip size, contract size and minimum unit step for 131 instruments, across forex pairs, metals, energies, indices, crypto futures, stocks and ETFs. |
|
|
18
|
+
| `pip_values()` | Pip value and the loss on a 20 pip move for standard, mini, micro and nano lots. |
|
|
19
|
+
| `losing_streak_equity()` | Equity remaining after 1 to 20 consecutive losses at 0.5%, 1% and 2% risk per trade. |
|
|
20
|
+
| `drawdown_recovery()` | Gain required on the reduced balance to return to the original balance, for drawdowns from 5% to 90%. |
|
|
21
|
+
| `position_size(...)` | The risk-to-units calculation itself. |
|
|
22
|
+
|
|
23
|
+
Read the tables:
|
|
24
|
+
|
|
25
|
+
```python
|
|
26
|
+
from position_sizing_data import contract_specifications
|
|
27
|
+
|
|
28
|
+
rows = contract_specifications()
|
|
29
|
+
print(rows[0])
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Compute a size:
|
|
33
|
+
|
|
34
|
+
```python
|
|
35
|
+
from position_sizing_data import position_size
|
|
36
|
+
|
|
37
|
+
result = position_size(
|
|
38
|
+
balance=10000.0,
|
|
39
|
+
risk_percent=1.0,
|
|
40
|
+
entry=1.1000,
|
|
41
|
+
stop=1.0980,
|
|
42
|
+
unit_step=1000.0, # 0.01 lot
|
|
43
|
+
)
|
|
44
|
+
print(result)
|
|
45
|
+
# {'risk_budget': 100.0, 'units': 50000.0, 'tradable_units': 50000.0, 'worst_case_loss': 100.0}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## The formula
|
|
49
|
+
|
|
50
|
+
```
|
|
51
|
+
units = (risk_budget - commission) / ((|entry - stop| + spread) x quote_rate)
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
The tradable size is that number rounded **down** to `unit_step`. `position_size` returns the worst-case loss recomputed from the rounded size, which is what the account actually loses when the stop is hit.
|
|
55
|
+
|
|
56
|
+
## Where the numbers come from
|
|
57
|
+
|
|
58
|
+
The rows in `contract_specifications()` are typical retail contract specifications, not exchange-published official values. Verify the contract size and unit step against your own broker before placing an order. The other three tables are closed-form arithmetic:
|
|
59
|
+
|
|
60
|
+
- losing streak: `remaining = (1 - risk)^n`
|
|
61
|
+
- drawdown recovery: `gain_required = 1 / (1 - drawdown) - 1`
|
|
62
|
+
- pip value: `pip_value = units x pip_size`
|
|
63
|
+
|
|
64
|
+
## Licence
|
|
65
|
+
|
|
66
|
+
MIT for the code. Data files are CC0 1.0 Universal, to the extent applicable. This is not investment advice.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "position-sizing-data"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Reference data and arithmetic for risk-based position sizing across forex, stocks and crypto futures"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.9"
|
|
11
|
+
license = "MIT"
|
|
12
|
+
authors = [{ name = "JUN YI" }]
|
|
13
|
+
keywords = ["position sizing", "risk management", "forex", "trading", "crypto"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 4 - Beta",
|
|
16
|
+
"Intended Audience :: Financial and Insurance Industry",
|
|
17
|
+
"Operating System :: OS Independent",
|
|
18
|
+
"Programming Language :: Python :: 3",
|
|
19
|
+
"Topic :: Office/Business :: Financial :: Investment",
|
|
20
|
+
]
|
|
21
|
+
dependencies = []
|
|
22
|
+
|
|
23
|
+
[project.urls]
|
|
24
|
+
Homepage = "https://positionsizetool.com/"
|
|
25
|
+
Repository = "https://github.com/tk25719/position-sizing-data"
|
|
26
|
+
Zenodo = "https://doi.org/10.5281/zenodo.22840538"
|
|
27
|
+
|
|
28
|
+
[tool.setuptools.packages.find]
|
|
29
|
+
where = ["src"]
|
|
30
|
+
|
|
31
|
+
[tool.setuptools.package-data]
|
|
32
|
+
position_sizing_data = ["data/*.csv"]
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
"""Reference data and arithmetic for risk-based position sizing.
|
|
2
|
+
|
|
3
|
+
This package ships the same CSV tables and the same risk-to-units formula that
|
|
4
|
+
are published as the Zenodo dataset 10.5281/zenodo.22840538 and used by the web
|
|
5
|
+
calculator at https://positionsizetool.com/.
|
|
6
|
+
|
|
7
|
+
The tables are plain data. The one function that computes something,
|
|
8
|
+
``position_size``, implements the formula::
|
|
9
|
+
|
|
10
|
+
units = (risk_budget - commission) / ((|entry - stop| + spread) x rate)
|
|
11
|
+
|
|
12
|
+
and rounds the result DOWN to the instrument's minimum unit step, because
|
|
13
|
+
rounding up raises risk without showing it anywhere.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
import csv
|
|
19
|
+
import math
|
|
20
|
+
from importlib import resources
|
|
21
|
+
from typing import Dict, List
|
|
22
|
+
|
|
23
|
+
__version__ = "0.1.0"
|
|
24
|
+
|
|
25
|
+
__all__ = [
|
|
26
|
+
"load_csv",
|
|
27
|
+
"contract_specifications",
|
|
28
|
+
"pip_values",
|
|
29
|
+
"losing_streak_equity",
|
|
30
|
+
"drawdown_recovery",
|
|
31
|
+
"position_size",
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
CSV_FILES = {
|
|
35
|
+
"contract-specifications.csv",
|
|
36
|
+
"pip-value-by-lot-size.csv",
|
|
37
|
+
"losing-streak-equity.csv",
|
|
38
|
+
"drawdown-recovery.csv",
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def load_csv(name: str) -> List[Dict[str, str]]:
|
|
43
|
+
"""Return one of the packaged CSV files as a list of dicts."""
|
|
44
|
+
if name not in CSV_FILES:
|
|
45
|
+
raise ValueError("unknown data file: " + name)
|
|
46
|
+
resource = resources.files(__package__).joinpath("data", name)
|
|
47
|
+
text = resource.read_text(encoding="utf-8-sig")
|
|
48
|
+
reader = csv.DictReader(text.splitlines())
|
|
49
|
+
return [dict(row) for row in reader]
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def contract_specifications() -> List[Dict[str, str]]:
|
|
53
|
+
"""Pip size, contract size and minimum step per instrument (131 rows)."""
|
|
54
|
+
return load_csv("contract-specifications.csv")
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def pip_values() -> List[Dict[str, str]]:
|
|
58
|
+
"""Pip value and loss on a 20 pip move for standard, mini, micro and nano lots."""
|
|
59
|
+
return load_csv("pip-value-by-lot-size.csv")
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def losing_streak_equity() -> List[Dict[str, str]]:
|
|
63
|
+
"""Equity remaining after n consecutive losses at 0.5%, 1% and 2% risk."""
|
|
64
|
+
return load_csv("losing-streak-equity.csv")
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def drawdown_recovery() -> List[Dict[str, str]]:
|
|
68
|
+
"""Gain required on the reduced balance to return to the original balance."""
|
|
69
|
+
return load_csv("drawdown-recovery.csv")
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def position_size(
|
|
73
|
+
balance: float,
|
|
74
|
+
risk_percent: float,
|
|
75
|
+
entry: float,
|
|
76
|
+
stop: float,
|
|
77
|
+
spread: float = 0.0,
|
|
78
|
+
commission: float = 0.0,
|
|
79
|
+
quote_rate: float = 1.0,
|
|
80
|
+
unit_step: float = 0.01,
|
|
81
|
+
) -> Dict[str, float]:
|
|
82
|
+
"""Convert a risk budget into a tradable unit count.
|
|
83
|
+
|
|
84
|
+
``balance`` and ``commission`` are in account currency. ``risk_percent`` is
|
|
85
|
+
expressed as a number (1 means 1%). ``quote_rate`` converts one unit of the
|
|
86
|
+
quote currency into account currency; leave it at 1.0 when they are the
|
|
87
|
+
same. ``unit_step`` is the broker's minimum increment.
|
|
88
|
+
|
|
89
|
+
The returned ``worst_case_loss`` is recomputed from the ROUNDED size, which
|
|
90
|
+
is the number that actually matters: it is what the account loses if the
|
|
91
|
+
stop is hit.
|
|
92
|
+
"""
|
|
93
|
+
budget = balance * risk_percent / 100.0
|
|
94
|
+
stop_distance = abs(entry - stop) + spread
|
|
95
|
+
if stop_distance <= 0:
|
|
96
|
+
raise ValueError("stop distance must be greater than zero")
|
|
97
|
+
if quote_rate <= 0:
|
|
98
|
+
raise ValueError("quote_rate must be greater than zero")
|
|
99
|
+
if unit_step <= 0:
|
|
100
|
+
raise ValueError("unit_step must be greater than zero")
|
|
101
|
+
units = (budget - commission) / (stop_distance * quote_rate)
|
|
102
|
+
tradable = math.floor(units / unit_step) * unit_step
|
|
103
|
+
worst_case = tradable * stop_distance * quote_rate + commission
|
|
104
|
+
return {
|
|
105
|
+
"risk_budget": budget,
|
|
106
|
+
"units": units,
|
|
107
|
+
"tradable_units": tradable,
|
|
108
|
+
"worst_case_loss": worst_case,
|
|
109
|
+
}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
symbol,asset_class,quote_currency,pip_size,contract_size,unit_step
|
|
2
|
+
AUD/USD,forex,USD,0.0001,100000,1000
|
|
3
|
+
EUR/USD,forex,USD,0.0001,100000,1000
|
|
4
|
+
GBP/USD,forex,USD,0.0001,100000,1000
|
|
5
|
+
NZD/USD,forex,USD,0.0001,100000,1000
|
|
6
|
+
USD/JPY,forex,JPY,0.01,100000,1000
|
|
7
|
+
USD/CHF,forex,CHF,0.0001,100000,1000
|
|
8
|
+
USD/CAD,forex,CAD,0.0001,100000,1000
|
|
9
|
+
USD/MXN,forex,MXN,0.0001,100000,1000
|
|
10
|
+
USD/ZAR,forex,ZAR,0.0001,100000,1000
|
|
11
|
+
USD/TRY,forex,TRY,0.0001,100000,1000
|
|
12
|
+
USD/SEK,forex,SEK,0.0001,100000,1000
|
|
13
|
+
USD/NOK,forex,NOK,0.0001,100000,1000
|
|
14
|
+
USD/DKK,forex,DKK,0.0001,100000,1000
|
|
15
|
+
USD/PLN,forex,PLN,0.0001,100000,1000
|
|
16
|
+
USD/HUF,forex,HUF,0.0001,100000,1000
|
|
17
|
+
USD/CZK,forex,CZK,0.0001,100000,1000
|
|
18
|
+
USD/SGD,forex,SGD,0.0001,100000,1000
|
|
19
|
+
USD/HKD,forex,HKD,0.0001,100000,1000
|
|
20
|
+
USD/CNH,forex,CNH,0.0001,100000,1000
|
|
21
|
+
USD/THB,forex,THB,0.0001,100000,1000
|
|
22
|
+
USD/MYR,forex,MYR,0.0001,100000,1000
|
|
23
|
+
USD/PHP,forex,PHP,0.0001,100000,1000
|
|
24
|
+
USD/IDR,forex,IDR,0.0001,100000,1000
|
|
25
|
+
USD/INR,forex,INR,0.0001,100000,1000
|
|
26
|
+
USD/KRW,forex,KRW,0.0001,100000,1000
|
|
27
|
+
EUR/JPY,forex,JPY,0.01,100000,1000
|
|
28
|
+
GBP/JPY,forex,JPY,0.01,100000,1000
|
|
29
|
+
AUD/JPY,forex,JPY,0.01,100000,1000
|
|
30
|
+
CAD/JPY,forex,JPY,0.01,100000,1000
|
|
31
|
+
CHF/JPY,forex,JPY,0.01,100000,1000
|
|
32
|
+
NZD/JPY,forex,JPY,0.01,100000,1000
|
|
33
|
+
EUR/GBP,forex,GBP,0.0001,100000,1000
|
|
34
|
+
EUR/AUD,forex,AUD,0.0001,100000,1000
|
|
35
|
+
EUR/CAD,forex,CAD,0.0001,100000,1000
|
|
36
|
+
EUR/CHF,forex,CHF,0.0001,100000,1000
|
|
37
|
+
EUR/NZD,forex,NZD,0.0001,100000,1000
|
|
38
|
+
EUR/SEK,forex,SEK,0.0001,100000,1000
|
|
39
|
+
EUR/NOK,forex,NOK,0.0001,100000,1000
|
|
40
|
+
EUR/DKK,forex,DKK,0.0001,100000,1000
|
|
41
|
+
EUR/PLN,forex,PLN,0.0001,100000,1000
|
|
42
|
+
EUR/TRY,forex,TRY,0.0001,100000,1000
|
|
43
|
+
EUR/ZAR,forex,ZAR,0.0001,100000,1000
|
|
44
|
+
EUR/MXN,forex,MXN,0.0001,100000,1000
|
|
45
|
+
EUR/HUF,forex,HUF,0.0001,100000,1000
|
|
46
|
+
EUR/CZK,forex,CZK,0.0001,100000,1000
|
|
47
|
+
EUR/SGD,forex,SGD,0.0001,100000,1000
|
|
48
|
+
EUR/HKD,forex,HKD,0.0001,100000,1000
|
|
49
|
+
GBP/AUD,forex,AUD,0.0001,100000,1000
|
|
50
|
+
GBP/CAD,forex,CAD,0.0001,100000,1000
|
|
51
|
+
GBP/CHF,forex,CHF,0.0001,100000,1000
|
|
52
|
+
GBP/NZD,forex,NZD,0.0001,100000,1000
|
|
53
|
+
GBP/SEK,forex,SEK,0.0001,100000,1000
|
|
54
|
+
GBP/NOK,forex,NOK,0.0001,100000,1000
|
|
55
|
+
GBP/PLN,forex,PLN,0.0001,100000,1000
|
|
56
|
+
GBP/ZAR,forex,ZAR,0.0001,100000,1000
|
|
57
|
+
GBP/TRY,forex,TRY,0.0001,100000,1000
|
|
58
|
+
GBP/SGD,forex,SGD,0.0001,100000,1000
|
|
59
|
+
AUD/CAD,forex,CAD,0.0001,100000,1000
|
|
60
|
+
AUD/CHF,forex,CHF,0.0001,100000,1000
|
|
61
|
+
AUD/NZD,forex,NZD,0.0001,100000,1000
|
|
62
|
+
AUD/SGD,forex,SGD,0.0001,100000,1000
|
|
63
|
+
AUD/HKD,forex,HKD,0.0001,100000,1000
|
|
64
|
+
CAD/CHF,forex,CHF,0.0001,100000,1000
|
|
65
|
+
NZD/CAD,forex,CAD,0.0001,100000,1000
|
|
66
|
+
NZD/CHF,forex,CHF,0.0001,100000,1000
|
|
67
|
+
NZD/SGD,forex,SGD,0.0001,100000,1000
|
|
68
|
+
CHF/PLN,forex,PLN,0.0001,100000,1000
|
|
69
|
+
XAU/USD,metal,USD,0.01,100,1
|
|
70
|
+
XAG/USD,metal,USD,0.001,5000,1
|
|
71
|
+
XPT/USD,metal,USD,0.01,100,1
|
|
72
|
+
XPD/USD,metal,USD,0.01,100,1
|
|
73
|
+
WTI/USD,energy,USD,0.01,1000,1
|
|
74
|
+
BRENT/USD,energy,USD,0.01,1000,1
|
|
75
|
+
NATGAS/USD,energy,USD,0.001,10000,1
|
|
76
|
+
US30,index,USD,1,1,1
|
|
77
|
+
US500,index,USD,1,1,1
|
|
78
|
+
USTEC,index,USD,1,1,1
|
|
79
|
+
DE40,index,USD,1,1,1
|
|
80
|
+
UK100,index,USD,1,1,1
|
|
81
|
+
JP225,index,USD,1,1,1
|
|
82
|
+
AUS200,index,USD,1,1,1
|
|
83
|
+
FRA40,index,USD,1,1,1
|
|
84
|
+
EU50,index,USD,1,1,1
|
|
85
|
+
SPA35,index,USD,1,1,1
|
|
86
|
+
HK50,index,USD,1,1,1
|
|
87
|
+
CHINA50,index,USD,1,1,1
|
|
88
|
+
BTCUSDT,crypto,USD,0.01,1,0.001
|
|
89
|
+
ETHUSDT,crypto,USD,0.01,1,0.001
|
|
90
|
+
SOLUSDT,crypto,USD,0.01,1,0.001
|
|
91
|
+
XRPUSDT,crypto,USD,0.01,1,0.001
|
|
92
|
+
ADAUSDT,crypto,USD,0.01,1,0.001
|
|
93
|
+
DOGEUSDT,crypto,USD,0.01,1,0.001
|
|
94
|
+
AVAXUSDT,crypto,USD,0.01,1,0.001
|
|
95
|
+
LINKUSDT,crypto,USD,0.01,1,0.001
|
|
96
|
+
DOTUSDT,crypto,USD,0.01,1,0.001
|
|
97
|
+
TONUSDT,crypto,USD,0.01,1,0.001
|
|
98
|
+
LTCUSDT,crypto,USD,0.01,1,0.001
|
|
99
|
+
BCHUSDT,crypto,USD,0.01,1,0.001
|
|
100
|
+
UNIUSDT,crypto,USD,0.01,1,0.001
|
|
101
|
+
ATOMUSDT,crypto,USD,0.01,1,0.001
|
|
102
|
+
TRXUSDT,crypto,USD,0.01,1,0.001
|
|
103
|
+
XLMUSDT,crypto,USD,0.01,1,0.001
|
|
104
|
+
NEARUSDT,crypto,USD,0.01,1,0.001
|
|
105
|
+
APTUSDT,crypto,USD,0.01,1,0.001
|
|
106
|
+
ARBUSDT,crypto,USD,0.01,1,0.001
|
|
107
|
+
OPUSDT,crypto,USD,0.01,1,0.001
|
|
108
|
+
SUIUSDT,crypto,USD,0.01,1,0.001
|
|
109
|
+
ICPUSDT,crypto,USD,0.01,1,0.001
|
|
110
|
+
FILUSDT,crypto,USD,0.01,1,0.001
|
|
111
|
+
INJUSDT,crypto,USD,0.01,1,0.001
|
|
112
|
+
AAVEUSDT,crypto,USD,0.01,1,0.001
|
|
113
|
+
GRTUSDT,crypto,USD,0.01,1,0.001
|
|
114
|
+
THETAUSDT,crypto,USD,0.01,1,0.001
|
|
115
|
+
EOSUSDT,crypto,USD,0.01,1,0.001
|
|
116
|
+
CHZUSDT,crypto,USD,0.01,1,0.001
|
|
117
|
+
SANDUSDT,crypto,USD,0.01,1,0.001
|
|
118
|
+
MANAUSDT,crypto,USD,0.01,1,0.001
|
|
119
|
+
AXSUSDT,crypto,USD,0.01,1,0.001
|
|
120
|
+
GALAUSDT,crypto,USD,0.01,1,0.001
|
|
121
|
+
IMXUSDT,crypto,USD,0.01,1,0.001
|
|
122
|
+
RUNEUSDT,crypto,USD,0.01,1,0.001
|
|
123
|
+
TIAUSDT,crypto,USD,0.01,1,0.001
|
|
124
|
+
SEIUSDT,crypto,USD,0.01,1,0.001
|
|
125
|
+
PEPEUSDT,crypto,USD,0.01,1,0.001
|
|
126
|
+
ORDIUSDT,crypto,USD,0.01,1,0.001
|
|
127
|
+
WIFUSDT,crypto,USD,0.01,1,0.001
|
|
128
|
+
BNBUSDT,crypto,USD,0.01,1,0.001
|
|
129
|
+
ETCUSDT,crypto,USD,0.01,1,0.001
|
|
130
|
+
VETUSDT,crypto,USD,0.01,1,0.001
|
|
131
|
+
Stock (your ticker),stock,USD,0.01,1,1
|
|
132
|
+
Custom instrument,custom,USD,0.0001,1,0.001
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
consecutive_losses,equity_remaining_0.5pct,equity_remaining_1pct,equity_remaining_2pct
|
|
2
|
+
1,99.50%,99.00%,98.00%
|
|
3
|
+
2,99.00%,98.01%,96.04%
|
|
4
|
+
3,98.51%,97.03%,94.12%
|
|
5
|
+
4,98.01%,96.06%,92.24%
|
|
6
|
+
5,97.52%,95.10%,90.39%
|
|
7
|
+
6,97.04%,94.15%,88.58%
|
|
8
|
+
7,96.55%,93.21%,86.81%
|
|
9
|
+
8,96.07%,92.27%,85.08%
|
|
10
|
+
9,95.59%,91.35%,83.37%
|
|
11
|
+
10,95.11%,90.44%,81.71%
|
|
12
|
+
11,94.64%,89.53%,80.07%
|
|
13
|
+
12,94.16%,88.64%,78.47%
|
|
14
|
+
13,93.69%,87.75%,76.90%
|
|
15
|
+
14,93.22%,86.87%,75.36%
|
|
16
|
+
15,92.76%,86.01%,73.86%
|
|
17
|
+
16,92.29%,85.15%,72.38%
|
|
18
|
+
17,91.83%,84.29%,70.93%
|
|
19
|
+
18,91.37%,83.45%,69.51%
|
|
20
|
+
19,90.92%,82.62%,68.12%
|
|
21
|
+
20,90.46%,81.79%,66.76%
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
lot,units,pip_value_usd_on_usd_quote_pair,pip_value_usd_on_jpy_pair_at_150_00,loss_on_20_pip_move_usd,spread_cost_of_1_pip_usd
|
|
2
|
+
standard,100000,10.0000,6.6667,200.00,10.0000
|
|
3
|
+
mini,10000,1.0000,0.6667,20.00,1.0000
|
|
4
|
+
micro,1000,0.1000,0.0667,2.00,0.1000
|
|
5
|
+
nano,100,0.0100,0.0067,0.20,0.0100
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: position-sizing-data
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Reference data and arithmetic for risk-based position sizing across forex, stocks and crypto futures
|
|
5
|
+
Author: JUN YI
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://positionsizetool.com/
|
|
8
|
+
Project-URL: Repository, https://github.com/tk25719/position-sizing-data
|
|
9
|
+
Project-URL: Zenodo, https://doi.org/10.5281/zenodo.22840538
|
|
10
|
+
Keywords: position sizing,risk management,forex,trading,crypto
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Financial and Insurance Industry
|
|
13
|
+
Classifier: Operating System :: OS Independent
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Topic :: Office/Business :: Financial :: Investment
|
|
16
|
+
Requires-Python: >=3.9
|
|
17
|
+
Description-Content-Type: text/markdown
|
|
18
|
+
License-File: LICENSE
|
|
19
|
+
Dynamic: license-file
|
|
20
|
+
|
|
21
|
+
# position-sizing-data
|
|
22
|
+
|
|
23
|
+
Reference data and arithmetic for risk-based position sizing across forex, stocks and crypto futures.
|
|
24
|
+
|
|
25
|
+
The same tables are published as a citable dataset: [doi:10.5281/zenodo.22840538](https://doi.org/10.5281/zenodo.22840538), and used by the web calculator at [https://positionsizetool.com/](https://positionsizetool.com/). Source repository: [https://github.com/tk25719/position-sizing-data](https://github.com/tk25719/position-sizing-data).
|
|
26
|
+
|
|
27
|
+
## Install
|
|
28
|
+
|
|
29
|
+
```console
|
|
30
|
+
pip install position-sizing-data
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## What is in it
|
|
34
|
+
|
|
35
|
+
| Function | Returns |
|
|
36
|
+
| --- | --- |
|
|
37
|
+
| `contract_specifications()` | Pip size, contract size and minimum unit step for 131 instruments, across forex pairs, metals, energies, indices, crypto futures, stocks and ETFs. |
|
|
38
|
+
| `pip_values()` | Pip value and the loss on a 20 pip move for standard, mini, micro and nano lots. |
|
|
39
|
+
| `losing_streak_equity()` | Equity remaining after 1 to 20 consecutive losses at 0.5%, 1% and 2% risk per trade. |
|
|
40
|
+
| `drawdown_recovery()` | Gain required on the reduced balance to return to the original balance, for drawdowns from 5% to 90%. |
|
|
41
|
+
| `position_size(...)` | The risk-to-units calculation itself. |
|
|
42
|
+
|
|
43
|
+
Read the tables:
|
|
44
|
+
|
|
45
|
+
```python
|
|
46
|
+
from position_sizing_data import contract_specifications
|
|
47
|
+
|
|
48
|
+
rows = contract_specifications()
|
|
49
|
+
print(rows[0])
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Compute a size:
|
|
53
|
+
|
|
54
|
+
```python
|
|
55
|
+
from position_sizing_data import position_size
|
|
56
|
+
|
|
57
|
+
result = position_size(
|
|
58
|
+
balance=10000.0,
|
|
59
|
+
risk_percent=1.0,
|
|
60
|
+
entry=1.1000,
|
|
61
|
+
stop=1.0980,
|
|
62
|
+
unit_step=1000.0, # 0.01 lot
|
|
63
|
+
)
|
|
64
|
+
print(result)
|
|
65
|
+
# {'risk_budget': 100.0, 'units': 50000.0, 'tradable_units': 50000.0, 'worst_case_loss': 100.0}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## The formula
|
|
69
|
+
|
|
70
|
+
```
|
|
71
|
+
units = (risk_budget - commission) / ((|entry - stop| + spread) x quote_rate)
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
The tradable size is that number rounded **down** to `unit_step`. `position_size` returns the worst-case loss recomputed from the rounded size, which is what the account actually loses when the stop is hit.
|
|
75
|
+
|
|
76
|
+
## Where the numbers come from
|
|
77
|
+
|
|
78
|
+
The rows in `contract_specifications()` are typical retail contract specifications, not exchange-published official values. Verify the contract size and unit step against your own broker before placing an order. The other three tables are closed-form arithmetic:
|
|
79
|
+
|
|
80
|
+
- losing streak: `remaining = (1 - risk)^n`
|
|
81
|
+
- drawdown recovery: `gain_required = 1 / (1 - drawdown) - 1`
|
|
82
|
+
- pip value: `pip_value = units x pip_size`
|
|
83
|
+
|
|
84
|
+
## Licence
|
|
85
|
+
|
|
86
|
+
MIT for the code. Data files are CC0 1.0 Universal, to the extent applicable. This is not investment advice.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
pyproject.toml
|
|
4
|
+
src/position_sizing_data/__init__.py
|
|
5
|
+
src/position_sizing_data.egg-info/PKG-INFO
|
|
6
|
+
src/position_sizing_data.egg-info/SOURCES.txt
|
|
7
|
+
src/position_sizing_data.egg-info/dependency_links.txt
|
|
8
|
+
src/position_sizing_data.egg-info/top_level.txt
|
|
9
|
+
src/position_sizing_data/data/contract-specifications.csv
|
|
10
|
+
src/position_sizing_data/data/drawdown-recovery.csv
|
|
11
|
+
src/position_sizing_data/data/losing-streak-equity.csv
|
|
12
|
+
src/position_sizing_data/data/pip-value-by-lot-size.csv
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
position_sizing_data
|