BackcastPro 0.0.1__py3-none-any.whl → 0.0.3__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.

Potentially problematic release.


This version of BackcastPro might be problematic. Click here for more details.

@@ -0,0 +1,174 @@
1
+ """
2
+ トレーディング戦略の基底クラス。
3
+ """
4
+
5
+ from __future__ import annotations
6
+
7
+ import sys
8
+ from abc import ABCMeta, abstractmethod
9
+ from typing import Optional, Tuple
10
+
11
+ import pandas as pd
12
+
13
+ # Import classes from their new modules
14
+ from .order import Order
15
+ from .position import Position
16
+ from .trade import Trade
17
+ from ._broker import _Broker
18
+
19
+ # pdoc(Pythonドキュメント生成ツール)の設定
20
+ # Falseを設定することで、該当するメソッドをドキュメントから除外
21
+ # 通常、__init__メソッドは内部実装の詳細であり、ユーザー向けドキュメントには不要
22
+ __pdoc__ = {
23
+ 'Strategy.__init__': False,
24
+ 'Order.__init__': False,
25
+ 'Position.__init__': False,
26
+ 'Trade.__init__': False,
27
+ }
28
+
29
+
30
+ class Strategy(metaclass=ABCMeta):
31
+ """
32
+ トレーディング戦略の基底クラス。このクラスを拡張し、
33
+ `backtesting.backtesting.Strategy.init` と
34
+ `backtesting.backtesting.Strategy.next` メソッドを
35
+ オーバーライドして独自の戦略を定義してください。
36
+ """
37
+
38
+ def __init__(self, broker: _Broker, data: pd.DataFrame):
39
+ """
40
+ これは Backtestクラスで初期化するためユーザーは不要
41
+ """
42
+ self._broker: _Broker = broker
43
+ self._data: pd.DataFrame = data
44
+
45
+
46
+ @abstractmethod
47
+ def init(self):
48
+ """
49
+ 戦略を初期化します。
50
+ このメソッドをオーバーライドしてください。
51
+ 戦略開始前に、事前計算が必要なものやベクトル化された方法で
52
+ 事前計算できるものを事前計算します。
53
+
54
+ `backtesting.lib`からコンポーザブル戦略を拡張する場合は、
55
+ 必ず以下を呼び出してください:
56
+
57
+ super().init()
58
+ """
59
+
60
+ @abstractmethod
61
+ def next(self):
62
+ """
63
+ メインのストラテジー実行メソッド。新しい
64
+ `backtesting.backtesting.Strategy.data`
65
+ インスタンス(行;完全なローソク足バー)が利用可能になるたびに呼び出されます。
66
+ これは、`backtesting.backtesting.Strategy.init`で
67
+ 事前計算されたデータに基づくストラテジーの意思決定が
68
+ 行われるメインメソッドです。
69
+
70
+ `backtesting.lib`からコンポーザブルストラテジーを拡張する場合は、
71
+ 必ず以下を呼び出してください:
72
+
73
+ super().next()
74
+ """
75
+
76
+
77
+ class __FULL_EQUITY(float): # noqa: N801
78
+ """
79
+ 利用可能資金のほぼ100%を表す特別な浮動小数点数クラス。
80
+ floatを継承し、表示時に'.9999'として表示される。
81
+ 浮動小数点の精度問題を回避し、安全な取引を可能にする。
82
+ """
83
+ def __repr__(self): return '.9999' # noqa: E704
84
+
85
+ # 利用可能資金のほぼ100%を使用するための特別な値
86
+ # 1 - sys.float_info.epsilonにより、浮動小数点の精度問題を回避し、
87
+ # 手数料やスプレッドを考慮した安全な取引を可能にする
88
+ _FULL_EQUITY = __FULL_EQUITY(1 - sys.float_info.epsilon)
89
+
90
+ def buy(self, *,
91
+ size: float = _FULL_EQUITY,
92
+ limit: Optional[float] = None,
93
+ stop: Optional[float] = None,
94
+ sl: Optional[float] = None,
95
+ tp: Optional[float] = None,
96
+ tag: object = None) -> 'Order':
97
+ """
98
+ 新しいロングオーダーを発注し、それを返します。パラメータの説明については、
99
+ `Order` とそのプロパティを参照してください。
100
+ `Backtest(..., trade_on_close=True)` で実行していない限り、
101
+ 成行注文は次のバーの始値で約定され、
102
+ その他の注文タイプ(指値、ストップ指値、ストップ成行)は
103
+ それぞれの条件が満たされたときに約定されます。
104
+
105
+ 既存のポジションをクローズするには、`Position.close()` と `Trade.close()` を参照してください。
106
+
107
+ `Strategy.sell()` も参照してください。
108
+ """
109
+ assert 0 < size < 1 or round(size) == size >= 1, \
110
+ "sizeは正の資産割合または正の整数単位である必要があります"
111
+ return self._broker.new_order(size, limit, stop, sl, tp, tag)
112
+
113
+ def sell(self, *,
114
+ size: float = _FULL_EQUITY,
115
+ limit: Optional[float] = None,
116
+ stop: Optional[float] = None,
117
+ sl: Optional[float] = None,
118
+ tp: Optional[float] = None,
119
+ tag: object = None) -> 'Order':
120
+ """
121
+ 新しいショートオーダーを発注し、それを返します。パラメータの説明については、
122
+ `Order` とそのプロパティを参照してください。
123
+
124
+ .. caution::
125
+ `self.sell(size=.1)` は、以下の場合を除いて、
126
+ 既存の `self.buy(size=.1)` トレードをクローズしないことに注意してください:
127
+
128
+ * バックテストが `exclusive_orders=True` で実行された場合、
129
+ * 両方のケースで原資産価格が等しく、
130
+ バックテストが `spread = commission = 0` で実行された場合。
131
+
132
+ トレードを明示的に終了するには、`Trade.close()` または `Position.close()` を使用してください。
133
+
134
+ `Strategy.buy()` も参照してください。
135
+
136
+ .. note::
137
+ 既存のロングポジションをクローズしたいだけの場合は、
138
+ `Position.close()` または `Trade.close()` を使用してください。
139
+ """
140
+ assert 0 < size < 1 or round(size) == size >= 1, \
141
+ "sizeは正の資産割合または正の整数単位である必要があります"
142
+ return self._broker.new_order(-size, limit, stop, sl, tp, tag)
143
+
144
+ @property
145
+ def equity(self) -> float:
146
+ """現在のアカウント資産(現金プラス資産)。"""
147
+ return self._broker.equity
148
+
149
+ @property
150
+ def data(self) -> pd.DataFrame:
151
+ """
152
+ 価格データは、`Backtest.__init__`に渡されるものと同じ
153
+ """
154
+ return self._data
155
+
156
+ @property
157
+ def position(self) -> 'Position':
158
+ """`Position` のインスタンス。"""
159
+ return self._broker.position
160
+
161
+ @property
162
+ def orders(self) -> 'Tuple[Order, ...]':
163
+ """実行待ちのオーダーリスト(`Order` を参照)。"""
164
+ return tuple(self._broker.orders)
165
+
166
+ @property
167
+ def trades(self) -> 'Tuple[Trade, ...]':
168
+ """アクティブなトレードリスト(`Trade` を参照)。"""
169
+ return tuple(self._broker.trades)
170
+
171
+ @property
172
+ def closed_trades(self) -> 'Tuple[Trade, ...]':
173
+ """決済済みトレードリスト(`Trade` を参照)。"""
174
+ return tuple(self._broker.closed_trades)
BackcastPro/trade.py ADDED
@@ -0,0 +1,195 @@
1
+ """
2
+ 取引管理モジュール。
3
+ """
4
+
5
+ import numpy as np
6
+ import pandas as pd
7
+ from copy import copy
8
+ from math import copysign
9
+ from typing import TYPE_CHECKING, Optional, Union
10
+
11
+ if TYPE_CHECKING:
12
+ from ._broker import _Broker
13
+ from .order import Order
14
+
15
+
16
+ class Trade:
17
+ """
18
+ `Order`が約定されると、アクティブな`Trade`が発生します。
19
+ アクティブな取引は`Strategy.trades`で、クローズされた決済済み取引は`Strategy.closed_trades`で見つけることができます。
20
+ """
21
+ def __init__(self, broker: '_Broker', size: int, entry_price: float, entry_bar, tag):
22
+ self.__broker = broker
23
+ self.__size = size
24
+ self.__entry_price = entry_price
25
+ self.__exit_price: Optional[float] = None
26
+ self.__entry_bar: int = entry_bar
27
+ self.__exit_bar: Optional[int] = None
28
+ self.__sl_order: Optional[Order] = None
29
+ self.__tp_order: Optional[Order] = None
30
+ self.__tag = tag
31
+ self._commissions = 0
32
+
33
+ def __repr__(self):
34
+ return f'<Trade size={self.__size} time={self.__entry_bar}-{self.__exit_bar or ""} ' \
35
+ f'price={self.__entry_price}-{self.__exit_price or ""} pl={self.pl:.0f}' \
36
+ f'{" tag=" + str(self.__tag) if self.__tag is not None else ""}>'
37
+
38
+ def _replace(self, **kwargs):
39
+ for k, v in kwargs.items():
40
+ setattr(self, f'_{self.__class__.__qualname__}__{k}', v)
41
+ return self
42
+
43
+ def _copy(self, **kwargs):
44
+ return copy(self)._replace(**kwargs)
45
+
46
+ def close(self, portion: float = 1.):
47
+ """次の市場価格で取引の`portion`をクローズする新しい`Order`を出します。"""
48
+ assert 0 < portion <= 1, "portion must be a fraction between 0 and 1"
49
+ # Ensure size is an int to avoid rounding errors on 32-bit OS
50
+ size = copysign(max(1, int(round(abs(self.__size) * portion))), -self.__size)
51
+ from .order import Order
52
+ order = Order(self.__broker, size, parent_trade=self, tag=self.__tag)
53
+ self.__broker.orders.insert(0, order)
54
+
55
+ # Fields getters
56
+
57
+ @property
58
+ def size(self):
59
+ """取引サイズ(ボリューム;ショート取引の場合は負の値)。"""
60
+ return self.__size
61
+
62
+ @property
63
+ def entry_price(self) -> float:
64
+ """取引エントリー価格。"""
65
+ return self.__entry_price
66
+
67
+ @property
68
+ def exit_price(self) -> Optional[float]:
69
+ """取引エグジット価格(取引がまだアクティブな場合はNone)。"""
70
+ return self.__exit_price
71
+
72
+ @property
73
+ def entry_bar(self) -> int:
74
+ """取引がエントリーされた時のローソク足バーのインデックス。"""
75
+ return self.__entry_bar
76
+
77
+ @property
78
+ def exit_bar(self) -> Optional[int]:
79
+ """
80
+ 取引がエグジットされた時のローソク足バーのインデックス
81
+ (取引がまだアクティブな場合はNone)。
82
+ """
83
+ return self.__exit_bar
84
+
85
+ @property
86
+ def tag(self):
87
+ """
88
+ この取引を開始した`Order`から継承されたタグ値。
89
+
90
+ 取引の追跡や条件付きロジック/サブグループ分析に使用できます。
91
+
92
+ `Order.tag`も参照してください。
93
+ """
94
+ return self.__tag
95
+
96
+ @property
97
+ def _sl_order(self):
98
+ return self.__sl_order
99
+
100
+ @property
101
+ def _tp_order(self):
102
+ return self.__tp_order
103
+
104
+ # Extra properties
105
+
106
+ @property
107
+ def entry_time(self) -> Union[pd.Timestamp, int]:
108
+ """取引がエントリーされた日時。"""
109
+ return self.__broker._data.index[self.__entry_bar]
110
+
111
+ @property
112
+ def exit_time(self) -> Optional[Union[pd.Timestamp, int]]:
113
+ """取引がエグジットされた日時。"""
114
+ if self.__exit_bar is None:
115
+ return None
116
+ return self.__broker._data.index[self.__exit_bar]
117
+
118
+ @property
119
+ def is_long(self):
120
+ """取引がロングの場合True(取引サイズが正の値)。"""
121
+ return self.__size > 0
122
+
123
+ @property
124
+ def is_short(self):
125
+ """取引がショートの場合True(取引サイズが負の値)。"""
126
+ return not self.is_long
127
+
128
+ @property
129
+ def pl(self):
130
+ """
131
+ 取引の利益(正の値)または損失(負の値)を現金単位で表示。
132
+ 手数料は取引がクローズされた後にのみ反映されます。
133
+ """
134
+ price = self.__exit_price or self.__broker.last_price
135
+ return (self.__size * (price - self.__entry_price)) - self._commissions
136
+
137
+ @property
138
+ def pl_pct(self):
139
+ """取引の利益(正の値)または損失(負の値)をパーセントで表示。"""
140
+ price = self.__exit_price or self.__broker.last_price
141
+ gross_pl_pct = copysign(1, self.__size) * (price / self.__entry_price - 1)
142
+
143
+ # 取引全体のサイズに対する手数料を個別単位に換算
144
+ commission_pct = self._commissions / (abs(self.__size) * self.__entry_price)
145
+ return gross_pl_pct - commission_pct
146
+
147
+ @property
148
+ def value(self):
149
+ """取引の総価値を現金単位で表示(ボリューム × 価格)。"""
150
+ price = self.__exit_price or self.__broker.last_price
151
+ return abs(self.__size) * price
152
+
153
+ # SL/TP management API
154
+
155
+ @property
156
+ def sl(self):
157
+ """
158
+ 取引をクローズするストップロス価格。
159
+
160
+ この変数は書き込み可能です。新しい価格値を割り当てることで、
161
+ 既存のSLオーダーを作成または修正します。
162
+ `None`を割り当てることでキャンセルできます。
163
+ """
164
+ return self.__sl_order and self.__sl_order.stop
165
+
166
+ @sl.setter
167
+ def sl(self, price: float):
168
+ self.__set_contingent('sl', price)
169
+
170
+ @property
171
+ def tp(self):
172
+ """
173
+ 取引をクローズするテイクプロフィット価格。
174
+
175
+ このプロパティは書き込み可能です。新しい価格値を割り当てることで、
176
+ 既存のTPオーダーを作成または修正します。
177
+ `None`を割り当てることでキャンセルできます。
178
+ """
179
+ return self.__tp_order and self.__tp_order.limit
180
+
181
+ @tp.setter
182
+ def tp(self, price: float):
183
+ self.__set_contingent('tp', price)
184
+
185
+ def __set_contingent(self, type, price):
186
+ assert type in ('sl', 'tp')
187
+ assert price is None or 0 < price < np.inf, f'Make sure 0 < price < inf! price: {price}'
188
+ attr = f'_{self.__class__.__qualname__}__{type}_order'
189
+ order: Order = getattr(self, attr)
190
+ if order:
191
+ order.cancel()
192
+ if price:
193
+ kwargs = {'stop': price} if type == 'sl' else {'limit': price}
194
+ order = self.__broker.new_order(-self.size, trade=self, tag=self.tag, **kwargs)
195
+ setattr(self, attr, order)
@@ -0,0 +1,59 @@
1
+ Metadata-Version: 2.4
2
+ Name: BackcastPro
3
+ Version: 0.0.3
4
+ Summary: トレーディング戦略のためのPythonバックテストライブラリ
5
+ Author-email: botterYosuke <yosuke.sasazawa@gmail.com>
6
+ Project-URL: Homepage, https://BackcastPro.github.io/BackcastPro/
7
+ Project-URL: Issues, https://github.com/BackcastPro/BackcastPro/issues
8
+ Project-URL: Logo, https://raw.githubusercontent.com/BackcastPro/BackcastPro/main/docs/img/logo.png
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Operating System :: OS Independent
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Requires-Python: >=3.9
13
+ Description-Content-Type: text/markdown
14
+
15
+ # BackcastPro
16
+
17
+ トレーディング戦略のためのPythonバックテストライブラリ。
18
+
19
+ ## インストール
20
+
21
+ ### PyPIから(エンドユーザー向け)
22
+
23
+ ```bash
24
+ pip install BackcastPro
25
+ ```
26
+
27
+ ### 開発用インストール
28
+
29
+ 開発用に、リポジトリをクローンして開発モードでインストールしてください:
30
+
31
+ ```bash
32
+ git clone <repository-url>
33
+ cd BackcastPro
34
+ pip install -e .
35
+ ```
36
+
37
+ **開発モードインストール(pip install -e .)**
38
+ - 上記で実行したpip install -e .コマンドは、プロジェクトを開発モードでインストールしました
39
+ - これにより、srcディレクトリが自動的にPythonパスに追加されます
40
+
41
+ ## 使用方法
42
+
43
+ ```python
44
+ from BackcastPro import Strategy, Backtest
45
+ from BackcastPro.lib import resample_apply
46
+
47
+ # ここにトレーディング戦略の実装を記述
48
+ ```
49
+
50
+ ## ドキュメント
51
+
52
+ - [PyPIへのデプロイ方法](./docs/How%20to%20deploy%20to%20PyPI.md)
53
+ - [サンプル](./docs/examples/)
54
+
55
+ ## バグ報告
56
+
57
+ バグを報告したり、[ディスカッションボード](https://discord.gg/fzJTbpzE)に投稿する前に、
58
+
59
+
@@ -0,0 +1,14 @@
1
+ BackcastPro/__init__.py,sha256=1PPRDL8uh_fE35shzswg3f1XrqVMNBJ1N6H7ZTqSzPg,191
2
+ BackcastPro/_broker.py,sha256=5n6SR9wqEZz2s68iIrp7x3v7vhh6zL8ichfoYZPsquA,18191
3
+ BackcastPro/_stats.py,sha256=Omcx4BgfddBvnmkYHn4b49TXqCgHYr9McKk46qMKNuM,7843
4
+ BackcastPro/backtest.py,sha256=jcLzq9kOFYpm0u3FdXen92kPfKxdMkM4COVS9pbc_kA,13947
5
+ BackcastPro/order.py,sha256=JuPJah6Mcm4Qr0wzOCex4hTmqXU96HGGRDiIl7_rsiQ,5636
6
+ BackcastPro/position.py,sha256=7G1fKrCLuW8QACN4mWNvR-6yrk_X9ERFLbqo97LKuX0,2236
7
+ BackcastPro/strategy.py,sha256=KhVXH62QxivI_6C3-7CxjXPXMQ--VMOL3as2iHBGegw,7207
8
+ BackcastPro/trade.py,sha256=8pDyIh96NmzPgEDkYB9h2lekHl3wdK6JeZ5Ix3y8wWQ,7162
9
+ BackcastPro/data/__init__.py,sha256=qSf674-OW7fQj48y6VqJW3Y_fSqwj9pAGhFS2u_s5ik,126
10
+ BackcastPro/data/datareader.py,sha256=dhJ6BBmj713rD_Ks8mKm2o1MiLf4uG3YwS3xnEb1_cw,6154
11
+ backcastpro-0.0.3.dist-info/METADATA,sha256=P-fyxj4jZWfnpIAYbQUmI1T0Eq-ZwsdEd3lWFmY9_wQ,1848
12
+ backcastpro-0.0.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
13
+ backcastpro-0.0.3.dist-info/top_level.txt,sha256=GiP-TX_Bc2jjwHS9cx0VCrW27e9JPbhWWnqGxa5B4Fs,12
14
+ backcastpro-0.0.3.dist-info/RECORD,,
BackcastPro/example.py DELETED
@@ -1,2 +0,0 @@
1
- def add_one(number):
2
- return number + 1
@@ -1,18 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: BackcastPro
3
- Version: 0.0.1
4
- Summary: A small example package
5
- Author-email: 笹澤ようすけ <yosuke.sasazawa@gmail.com>
6
- Project-URL: Homepage, https://BackcastPro.github.io/BackcastPro/
7
- Project-URL: Issues, https://github.com/BackcastPro/BackcastPro/issues
8
- Classifier: Programming Language :: Python :: 3
9
- Classifier: Operating System :: OS Independent
10
- Classifier: License :: OSI Approved :: MIT License
11
- Requires-Python: >=3.9
12
- Description-Content-Type: text/markdown
13
-
14
- # Example Package
15
-
16
- This is a simple example package. You can use
17
- [GitHub-flavored Markdown](https://guides.github.com/features/mastering-markdown/)
18
- to write your content.
@@ -1,6 +0,0 @@
1
- BackcastPro/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- BackcastPro/example.py,sha256=X4bE2aofVJAbmacOI_Ny0Oc7m2Ru4ShxUscmJqVps1Q,43
3
- backcastpro-0.0.1.dist-info/METADATA,sha256=XC8ETHW_-JRmAG_frw-tkAfHkrNEqXyReg_JwK-EGyw,685
4
- backcastpro-0.0.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
5
- backcastpro-0.0.1.dist-info/top_level.txt,sha256=GiP-TX_Bc2jjwHS9cx0VCrW27e9JPbhWWnqGxa5B4Fs,12
6
- backcastpro-0.0.1.dist-info/RECORD,,