position-sizing-data 0.1.0__py3-none-any.whl

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.
@@ -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,13 @@
1
+ drawdown_pct,gain_required_pct_to_recover
2
+ 5%,5.3%
3
+ 10%,11.1%
4
+ 15%,17.6%
5
+ 20%,25.0%
6
+ 25%,33.3%
7
+ 30%,42.9%
8
+ 40%,66.7%
9
+ 50%,100.0%
10
+ 60%,150.0%
11
+ 70%,233.3%
12
+ 80%,400.0%
13
+ 90%,900.0%
@@ -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,10 @@
1
+ position_sizing_data/__init__.py,sha256=pSBz5CprBIfyuVapzfkPGor2DYFrW4VHlURHAjw2vOw,3646
2
+ position_sizing_data/data/contract-specifications.csv,sha256=eaIfgbanUpT6XTKlswKxgX0h4FFe6vztN7UArZ_G3eU,4485
3
+ position_sizing_data/data/drawdown-recovery.csv,sha256=sDAMSezWTSW-ZkZ7Vq0DqsVDa_sLuNCEuo2OyVN1BEA,165
4
+ position_sizing_data/data/losing-streak-equity.csv,sha256=20Shj9jLCPGOAFmeGiCVyIX_GA6A34TWFAUFhkuOhpg,558
5
+ position_sizing_data/data/pip-value-by-lot-size.csv,sha256=kY2by7SCwJMnsgUpSfhsg6obxn3u4MV2tavxqMyg1l4,283
6
+ position_sizing_data-0.1.0.dist-info/licenses/LICENSE,sha256=ihGu_DtcWzGVUBABtwMPQBzVLUehZDDc6Ymdcp1DWtU,1073
7
+ position_sizing_data-0.1.0.dist-info/METADATA,sha256=-zUmS6Sd7FJpmqIcPWndeoMIhbgcCiyGkxolh1A-pdE,3366
8
+ position_sizing_data-0.1.0.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
9
+ position_sizing_data-0.1.0.dist-info/top_level.txt,sha256=j3kmgA7xvWfzOaOYmInbW8_lKhVaAcodGSVXLG7AVSU,21
10
+ position_sizing_data-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (84.0.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -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 @@
1
+ position_sizing_data