BackcastPro 0.3.4__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.
- BackcastPro/__init__.py +28 -0
- BackcastPro/_broker.py +430 -0
- BackcastPro/_stats.py +177 -0
- BackcastPro/api/__init__.py +4 -0
- BackcastPro/api/board.py +130 -0
- BackcastPro/api/chart.py +527 -0
- BackcastPro/api/db_manager.py +283 -0
- BackcastPro/api/db_stocks_board.py +428 -0
- BackcastPro/api/db_stocks_daily.py +507 -0
- BackcastPro/api/db_stocks_info.py +260 -0
- BackcastPro/api/lib/__init__.py +4 -0
- BackcastPro/api/lib/e_api.py +588 -0
- BackcastPro/api/lib/jquants.py +384 -0
- BackcastPro/api/lib/kabusap.py +222 -0
- BackcastPro/api/lib/stooq.py +409 -0
- BackcastPro/api/lib/util.py +38 -0
- BackcastPro/api/stocks_board.py +77 -0
- BackcastPro/api/stocks_info.py +88 -0
- BackcastPro/api/stocks_price.py +131 -0
- BackcastPro/backtest.py +594 -0
- BackcastPro/order.py +161 -0
- BackcastPro/position.py +60 -0
- BackcastPro/trade.py +227 -0
- backcastpro-0.3.4.dist-info/METADATA +112 -0
- backcastpro-0.3.4.dist-info/RECORD +26 -0
- backcastpro-0.3.4.dist-info/WHEEL +4 -0
BackcastPro/order.py
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
"""
|
|
2
|
+
注文管理モジュール。
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from typing import TYPE_CHECKING, Optional
|
|
6
|
+
|
|
7
|
+
if TYPE_CHECKING:
|
|
8
|
+
from ._broker import _Broker
|
|
9
|
+
from .trade import Trade
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class Order:
|
|
13
|
+
"""
|
|
14
|
+
`Strategy.buy()`と`Strategy.sell()`を通じて新しい注文を出します。
|
|
15
|
+
`Strategy.orders`を通じて既存の注文を照会します。
|
|
16
|
+
|
|
17
|
+
注文が実行または[約定]されると、`Trade`が発生します。
|
|
18
|
+
|
|
19
|
+
出されたがまだ約定されていない注文の側面を変更したい場合は、
|
|
20
|
+
キャンセルして新しい注文を出してください。
|
|
21
|
+
|
|
22
|
+
すべての出された注文は[取消注文まで有効]です。
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
def __init__(self, broker: '_Broker',
|
|
26
|
+
code: str,
|
|
27
|
+
size: float,
|
|
28
|
+
limit_price: Optional[float] = None,
|
|
29
|
+
stop_price: Optional[float] = None,
|
|
30
|
+
sl_price: Optional[float] = None,
|
|
31
|
+
tp_price: Optional[float] = None,
|
|
32
|
+
parent_trade: Optional['Trade'] = None,
|
|
33
|
+
tag: object = None):
|
|
34
|
+
self.__code = code
|
|
35
|
+
self.__broker = broker
|
|
36
|
+
assert size != 0
|
|
37
|
+
self.__size = size
|
|
38
|
+
self.__limit_price = limit_price
|
|
39
|
+
self.__stop_price = stop_price
|
|
40
|
+
self.__sl_price = sl_price
|
|
41
|
+
self.__tp_price = tp_price
|
|
42
|
+
self.__parent_trade = parent_trade
|
|
43
|
+
self.__tag = tag
|
|
44
|
+
|
|
45
|
+
def _replace(self, **kwargs):
|
|
46
|
+
for k, v in kwargs.items():
|
|
47
|
+
setattr(self, f'_{self.__class__.__qualname__}__{k}', v)
|
|
48
|
+
return self
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def cancel(self):
|
|
52
|
+
"""注文をキャンセルします。"""
|
|
53
|
+
self.__broker.orders.remove(self)
|
|
54
|
+
trade = self.__parent_trade
|
|
55
|
+
if trade:
|
|
56
|
+
if self is trade._sl_order:
|
|
57
|
+
trade._replace(sl_order=None)
|
|
58
|
+
elif self is trade._tp_order:
|
|
59
|
+
trade._replace(tp_order=None)
|
|
60
|
+
else:
|
|
61
|
+
pass # Order placed by Trade.close()
|
|
62
|
+
|
|
63
|
+
# Fields getters
|
|
64
|
+
|
|
65
|
+
@property
|
|
66
|
+
def code(self) -> str:
|
|
67
|
+
"""
|
|
68
|
+
注文対象の銘柄コード。
|
|
69
|
+
"""
|
|
70
|
+
return self.__code
|
|
71
|
+
|
|
72
|
+
@property
|
|
73
|
+
def size(self) -> float:
|
|
74
|
+
"""
|
|
75
|
+
注文サイズ(ショート注文の場合は負の値)。
|
|
76
|
+
|
|
77
|
+
サイズが0と1の間の値の場合、現在利用可能な流動性(現金 + `Position.pl` - 使用済みマージン)の
|
|
78
|
+
割合として解釈されます。
|
|
79
|
+
1以上の値は絶対的なユニット数を示します。
|
|
80
|
+
"""
|
|
81
|
+
return self.__size
|
|
82
|
+
|
|
83
|
+
@property
|
|
84
|
+
def limit(self) -> Optional[float]:
|
|
85
|
+
"""
|
|
86
|
+
[指値注文]の注文指値価格、または[成行注文]の場合はNone(次に利用可能な価格で約定)。
|
|
87
|
+
|
|
88
|
+
[limit orders]: https://www.investopedia.com/terms/l/limitorder.asp
|
|
89
|
+
[market orders]: https://www.investopedia.com/terms/m/marketorder.asp
|
|
90
|
+
"""
|
|
91
|
+
return self.__limit_price
|
|
92
|
+
|
|
93
|
+
@property
|
|
94
|
+
def stop(self) -> Optional[float]:
|
|
95
|
+
"""
|
|
96
|
+
[ストップリミット/ストップ成行]注文の注文ストップ価格。
|
|
97
|
+
ストップが設定されていない場合、またはストップ価格が既にヒットした場合はNone。
|
|
98
|
+
|
|
99
|
+
[_]: https://www.investopedia.com/terms/s/stoporder.asp
|
|
100
|
+
"""
|
|
101
|
+
return self.__stop_price
|
|
102
|
+
|
|
103
|
+
@property
|
|
104
|
+
def sl(self) -> Optional[float]:
|
|
105
|
+
"""
|
|
106
|
+
ストップロス価格。設定されている場合、この注文の実行後に`Trade`に対して
|
|
107
|
+
新しい条件付きストップ成行注文が配置されます。
|
|
108
|
+
`Trade.sl`も参照してください。
|
|
109
|
+
"""
|
|
110
|
+
return self.__sl_price
|
|
111
|
+
|
|
112
|
+
@property
|
|
113
|
+
def tp(self) -> Optional[float]:
|
|
114
|
+
"""
|
|
115
|
+
テイクプロフィット価格。設定されている場合、この注文の実行後に`Trade`に対して
|
|
116
|
+
新しい条件付き指値注文が配置されます。
|
|
117
|
+
`Trade.tp`も参照してください。
|
|
118
|
+
"""
|
|
119
|
+
return self.__tp_price
|
|
120
|
+
|
|
121
|
+
@property
|
|
122
|
+
def parent_trade(self):
|
|
123
|
+
return self.__parent_trade
|
|
124
|
+
|
|
125
|
+
@property
|
|
126
|
+
def tag(self):
|
|
127
|
+
"""
|
|
128
|
+
任意の値(文字列など)。設定されている場合、この注文と関連する`Trade`の
|
|
129
|
+
追跡が可能になります(`Trade.tag`を参照)。
|
|
130
|
+
"""
|
|
131
|
+
return self.__tag
|
|
132
|
+
|
|
133
|
+
__pdoc__ = {'Order.parent_trade': False}
|
|
134
|
+
|
|
135
|
+
# Extra properties
|
|
136
|
+
|
|
137
|
+
@property
|
|
138
|
+
def is_long(self):
|
|
139
|
+
"""注文がロングの場合(注文サイズが正)にTrueを返します。"""
|
|
140
|
+
return self.__size > 0
|
|
141
|
+
|
|
142
|
+
@property
|
|
143
|
+
def is_short(self):
|
|
144
|
+
"""注文がショートの場合(注文サイズが負)にTrueを返します。"""
|
|
145
|
+
return self.__size < 0
|
|
146
|
+
|
|
147
|
+
@property
|
|
148
|
+
def is_contingent(self):
|
|
149
|
+
"""
|
|
150
|
+
[条件付き]注文、つまりアクティブな取引に配置された[OCO]ストップロスおよび
|
|
151
|
+
テイクプロフィットブラケット注文の場合にTrueを返します。
|
|
152
|
+
親`Trade`がクローズされると、残りの条件付き注文はキャンセルされます。
|
|
153
|
+
|
|
154
|
+
`Trade.sl`と`Trade.tp`を通じて条件付き注文を変更できます。
|
|
155
|
+
|
|
156
|
+
[contingent]: https://www.investopedia.com/terms/c/contingentorder.asp
|
|
157
|
+
[OCO]: https://www.investopedia.com/terms/o/oco.asp
|
|
158
|
+
"""
|
|
159
|
+
return bool((parent := self.__parent_trade) and
|
|
160
|
+
(self is parent._sl_order or
|
|
161
|
+
self is parent._tp_order))
|
BackcastPro/position.py
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"""
|
|
2
|
+
ポジション管理モジュール。
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from typing import TYPE_CHECKING
|
|
6
|
+
|
|
7
|
+
if TYPE_CHECKING:
|
|
8
|
+
from ._broker import _Broker
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class Position:
|
|
12
|
+
"""
|
|
13
|
+
現在保有している資産ポジション。
|
|
14
|
+
`backtesting.backtesting.Strategy.next`内で
|
|
15
|
+
`backtesting.backtesting.Strategy.position`として利用可能です。
|
|
16
|
+
ブール値コンテキストで使用できます。例:
|
|
17
|
+
|
|
18
|
+
if self.position:
|
|
19
|
+
... # ポジションがあります(ロングまたはショート)
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
def __init__(self, broker: '_Broker'):
|
|
23
|
+
self.__broker = broker
|
|
24
|
+
|
|
25
|
+
def __bool__(self):
|
|
26
|
+
return self.size != 0
|
|
27
|
+
|
|
28
|
+
@property
|
|
29
|
+
def size(self) -> float:
|
|
30
|
+
"""資産単位でのポジションサイズ。ショートポジションの場合は負の値。"""
|
|
31
|
+
return sum(trade.size for trade in self.__broker.trades)
|
|
32
|
+
|
|
33
|
+
@property
|
|
34
|
+
def pl(self) -> float:
|
|
35
|
+
"""現在のポジションの利益(正)または損失(負)を現金単位で。"""
|
|
36
|
+
return sum(trade.pl for trade in self.__broker.trades)
|
|
37
|
+
|
|
38
|
+
@property
|
|
39
|
+
def pl_pct(self) -> float:
|
|
40
|
+
"""現在のポジションの利益(正)または損失(負)をパーセントで。"""
|
|
41
|
+
total_invested = sum(trade.entry_price * abs(trade.size) for trade in self.__broker.trades)
|
|
42
|
+
return (self.pl / total_invested) * 100 if total_invested else 0
|
|
43
|
+
|
|
44
|
+
@property
|
|
45
|
+
def is_long(self) -> bool:
|
|
46
|
+
"""ポジションがロング(ポジションサイズが正)の場合True。"""
|
|
47
|
+
return self.size > 0
|
|
48
|
+
|
|
49
|
+
@property
|
|
50
|
+
def is_short(self) -> bool:
|
|
51
|
+
"""ポジションがショート(ポジションサイズが負)の場合True。"""
|
|
52
|
+
return self.size < 0
|
|
53
|
+
|
|
54
|
+
def close(self, portion: float = 1.):
|
|
55
|
+
"""
|
|
56
|
+
各アクティブな取引の「一部」を決済することで、ポジションの一部を決済します。詳細は「Trade.close」を参照してください。
|
|
57
|
+
"""
|
|
58
|
+
for trade in self.__broker.trades:
|
|
59
|
+
trade.close(portion)
|
|
60
|
+
|
BackcastPro/trade.py
ADDED
|
@@ -0,0 +1,227 @@
|
|
|
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', code: str, size: int, entry_price: float, entry_time: Union[pd.Timestamp, int], tag):
|
|
22
|
+
self.__broker = broker
|
|
23
|
+
self.__code = code
|
|
24
|
+
self.__size = size
|
|
25
|
+
self.__entry_price = entry_price
|
|
26
|
+
self.__exit_price: Optional[float] = None
|
|
27
|
+
self.__entry_time: Union[pd.Timestamp, int] = entry_time
|
|
28
|
+
self.__exit_time: Optional[Union[pd.Timestamp, int]] = None
|
|
29
|
+
self.__sl_order: Optional[Order] = None
|
|
30
|
+
self.__tp_order: Optional[Order] = None
|
|
31
|
+
self.__tag = tag
|
|
32
|
+
self._commissions = 0
|
|
33
|
+
|
|
34
|
+
def _replace(self, **kwargs):
|
|
35
|
+
for k, v in kwargs.items():
|
|
36
|
+
setattr(self, f'_{self.__class__.__qualname__}__{k}', v)
|
|
37
|
+
return self
|
|
38
|
+
|
|
39
|
+
def _copy(self, **kwargs):
|
|
40
|
+
return copy(self)._replace(**kwargs)
|
|
41
|
+
|
|
42
|
+
def close(self, portion: float = 1.):
|
|
43
|
+
"""次の市場価格で取引の`portion`をクローズする新しい`Order`を出します。"""
|
|
44
|
+
assert 0 < portion <= 1, "portion must be a fraction between 0 and 1"
|
|
45
|
+
# Ensure size is an int to avoid rounding errors on 32-bit OS
|
|
46
|
+
size = copysign(max(1, int(round(abs(self.__size) * portion))), -self.__size)
|
|
47
|
+
from .order import Order
|
|
48
|
+
order = Order(self.__broker, self.__code, size, parent_trade=self, tag=self.__tag)
|
|
49
|
+
self.__broker.orders.insert(0, order)
|
|
50
|
+
|
|
51
|
+
# Fields getters
|
|
52
|
+
|
|
53
|
+
@property
|
|
54
|
+
def code(self):
|
|
55
|
+
"""取引対象銘柄"""
|
|
56
|
+
return self.__code
|
|
57
|
+
|
|
58
|
+
@property
|
|
59
|
+
def size(self):
|
|
60
|
+
"""取引サイズ(ボリューム;ショート取引の場合は負の値)。"""
|
|
61
|
+
return self.__size
|
|
62
|
+
|
|
63
|
+
@property
|
|
64
|
+
def entry_price(self) -> float:
|
|
65
|
+
"""取引エントリー価格。"""
|
|
66
|
+
return self.__entry_price
|
|
67
|
+
|
|
68
|
+
@property
|
|
69
|
+
def exit_price(self) -> Optional[float]:
|
|
70
|
+
"""取引エグジット価格(取引がまだアクティブな場合はNone)。"""
|
|
71
|
+
return self.__exit_price
|
|
72
|
+
|
|
73
|
+
@property
|
|
74
|
+
def entry_bar(self) -> int:
|
|
75
|
+
"""
|
|
76
|
+
取引がエントリーされた時のローソク足バーのインデックス。
|
|
77
|
+
|
|
78
|
+
.. deprecated:: 0.1.0
|
|
79
|
+
`entry_time`プロパティを使用してください。
|
|
80
|
+
"""
|
|
81
|
+
import warnings
|
|
82
|
+
warnings.warn(
|
|
83
|
+
"entry_barプロパティは非推奨です。entry_timeプロパティを使用してください。",
|
|
84
|
+
DeprecationWarning,
|
|
85
|
+
stacklevel=2
|
|
86
|
+
)
|
|
87
|
+
# データからインデックスを逆算
|
|
88
|
+
try:
|
|
89
|
+
data_index = self.__broker._data[self.__code].index
|
|
90
|
+
return data_index.get_loc(self.__entry_time)
|
|
91
|
+
except (KeyError, TypeError):
|
|
92
|
+
# インデックスが見つからない場合は0を返す
|
|
93
|
+
return 0
|
|
94
|
+
|
|
95
|
+
@property
|
|
96
|
+
def exit_bar(self) -> Optional[int]:
|
|
97
|
+
"""
|
|
98
|
+
取引がエグジットされた時のローソク足バーのインデックス
|
|
99
|
+
(取引がまだアクティブな場合はNone)。
|
|
100
|
+
|
|
101
|
+
.. deprecated:: 0.1.0
|
|
102
|
+
`exit_time`プロパティを使用してください。
|
|
103
|
+
"""
|
|
104
|
+
import warnings
|
|
105
|
+
warnings.warn(
|
|
106
|
+
"exit_barプロパティは非推奨です。exit_timeプロパティを使用してください。",
|
|
107
|
+
DeprecationWarning,
|
|
108
|
+
stacklevel=2
|
|
109
|
+
)
|
|
110
|
+
if self.__exit_time is None:
|
|
111
|
+
return None
|
|
112
|
+
try:
|
|
113
|
+
data_index = self.__broker._data[self.__code].index
|
|
114
|
+
return data_index.get_loc(self.__exit_time)
|
|
115
|
+
except (KeyError, TypeError):
|
|
116
|
+
# インデックスが見つからない場合はNoneを返す
|
|
117
|
+
return None
|
|
118
|
+
|
|
119
|
+
@property
|
|
120
|
+
def entry_time(self) -> Union[pd.Timestamp, int]:
|
|
121
|
+
"""取引がエントリーされた日時。"""
|
|
122
|
+
return self.__entry_time
|
|
123
|
+
|
|
124
|
+
@property
|
|
125
|
+
def exit_time(self) -> Optional[Union[pd.Timestamp, int]]:
|
|
126
|
+
"""取引がエグジットされた日時。"""
|
|
127
|
+
return self.__exit_time
|
|
128
|
+
|
|
129
|
+
@property
|
|
130
|
+
def tag(self):
|
|
131
|
+
"""
|
|
132
|
+
この取引を開始した`Order`から継承されたタグ値。
|
|
133
|
+
|
|
134
|
+
取引の追跡や条件付きロジック/サブグループ分析に使用できます。
|
|
135
|
+
|
|
136
|
+
`Order.tag`も参照してください。
|
|
137
|
+
"""
|
|
138
|
+
return self.__tag
|
|
139
|
+
|
|
140
|
+
@property
|
|
141
|
+
def _sl_order(self):
|
|
142
|
+
return self.__sl_order
|
|
143
|
+
|
|
144
|
+
@property
|
|
145
|
+
def _tp_order(self):
|
|
146
|
+
return self.__tp_order
|
|
147
|
+
|
|
148
|
+
# Extra properties
|
|
149
|
+
|
|
150
|
+
@property
|
|
151
|
+
def is_long(self):
|
|
152
|
+
"""取引がロングの場合True(取引サイズが正の値)。"""
|
|
153
|
+
return self.__size > 0
|
|
154
|
+
|
|
155
|
+
@property
|
|
156
|
+
def is_short(self):
|
|
157
|
+
"""取引がショートの場合True(取引サイズが負の値)。"""
|
|
158
|
+
return not self.is_long
|
|
159
|
+
|
|
160
|
+
@property
|
|
161
|
+
def pl(self):
|
|
162
|
+
"""
|
|
163
|
+
取引の利益(正の値)または損失(負の値)を現金単位で表示。
|
|
164
|
+
手数料は取引がクローズされた後にのみ反映されます。
|
|
165
|
+
"""
|
|
166
|
+
price = self.__exit_price or self.__broker.last_price(self.__code)
|
|
167
|
+
return (self.__size * (price - self.__entry_price)) - self._commissions
|
|
168
|
+
|
|
169
|
+
@property
|
|
170
|
+
def pl_pct(self):
|
|
171
|
+
"""取引の利益(正の値)または損失(負の値)をパーセントで表示。"""
|
|
172
|
+
price = self.__exit_price or self.__broker.last_price(self.__code)
|
|
173
|
+
gross_pl_pct = copysign(1, self.__size) * (price / self.__entry_price - 1)
|
|
174
|
+
|
|
175
|
+
# 取引全体のサイズに対する手数料を個別単位に換算
|
|
176
|
+
commission_pct = self._commissions / (abs(self.__size) * self.__entry_price)
|
|
177
|
+
return gross_pl_pct - commission_pct
|
|
178
|
+
|
|
179
|
+
@property
|
|
180
|
+
def value(self):
|
|
181
|
+
"""取引の総価値を現金単位で表示(ボリューム × 価格)。"""
|
|
182
|
+
price = self.__exit_price or self.__broker.last_price(self.__code)
|
|
183
|
+
return abs(self.__size) * price
|
|
184
|
+
|
|
185
|
+
# SL/TP management API
|
|
186
|
+
|
|
187
|
+
@property
|
|
188
|
+
def sl(self):
|
|
189
|
+
"""
|
|
190
|
+
取引をクローズするストップロス価格。
|
|
191
|
+
|
|
192
|
+
この変数は書き込み可能です。新しい価格値を割り当てることで、
|
|
193
|
+
既存のSLオーダーを作成または修正します。
|
|
194
|
+
`None`を割り当てることでキャンセルできます。
|
|
195
|
+
"""
|
|
196
|
+
return self.__sl_order and self.__sl_order.stop
|
|
197
|
+
|
|
198
|
+
@sl.setter
|
|
199
|
+
def sl(self, price: float):
|
|
200
|
+
self.__set_contingent('sl', price)
|
|
201
|
+
|
|
202
|
+
@property
|
|
203
|
+
def tp(self):
|
|
204
|
+
"""
|
|
205
|
+
取引をクローズするテイクプロフィット価格。
|
|
206
|
+
|
|
207
|
+
このプロパティは書き込み可能です。新しい価格値を割り当てることで、
|
|
208
|
+
既存のTPオーダーを作成または修正します。
|
|
209
|
+
`None`を割り当てることでキャンセルできます。
|
|
210
|
+
"""
|
|
211
|
+
return self.__tp_order and self.__tp_order.limit
|
|
212
|
+
|
|
213
|
+
@tp.setter
|
|
214
|
+
def tp(self, price: float):
|
|
215
|
+
self.__set_contingent('tp', price)
|
|
216
|
+
|
|
217
|
+
def __set_contingent(self, type, price):
|
|
218
|
+
assert type in ('sl', 'tp')
|
|
219
|
+
assert price is None or 0 < price < np.inf, f'Make sure 0 < price < inf! price: {price}'
|
|
220
|
+
attr = f'_{self.__class__.__qualname__}__{type}_order'
|
|
221
|
+
order: Order = getattr(self, attr)
|
|
222
|
+
if order:
|
|
223
|
+
order.cancel()
|
|
224
|
+
if price:
|
|
225
|
+
kwargs = {'stop': price} if type == 'sl' else {'limit': price}
|
|
226
|
+
order = self.__broker.new_order(self.code, -self.size, trade=self, tag=self.tag, **kwargs)
|
|
227
|
+
setattr(self, attr, order)
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: BackcastPro
|
|
3
|
+
Version: 0.3.4
|
|
4
|
+
Summary: トレーディング戦略のためのPythonバックテストライブラリ
|
|
5
|
+
Project-URL: Homepage, https://github.com/botterYosuke/BackcastPro/
|
|
6
|
+
Project-URL: Issues, https://github.com/botterYosuke/BackcastPro/issues
|
|
7
|
+
Project-URL: Logo, https://raw.githubusercontent.com/botterYosuke/BackcastPro/main/docs/img/logo.drawio.svg
|
|
8
|
+
Author: botterYosuke
|
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
+
Classifier: Operating System :: OS Independent
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Requires-Python: >=3.9
|
|
17
|
+
Requires-Dist: anywidget>=0.9.21
|
|
18
|
+
Requires-Dist: duckdb>=0.9.0
|
|
19
|
+
Requires-Dist: matplotlib>=3.0.0
|
|
20
|
+
Requires-Dist: numpy>=1.20.0
|
|
21
|
+
Requires-Dist: pandas>=1.3.0
|
|
22
|
+
Requires-Dist: plotly>=5.0.0
|
|
23
|
+
Requires-Dist: python-dotenv>=0.19.0
|
|
24
|
+
Requires-Dist: requests>=2.25.0
|
|
25
|
+
Requires-Dist: scipy>=1.7.0
|
|
26
|
+
Provides-Extra: all
|
|
27
|
+
Requires-Dist: yfinance>=0.2.0; extra == 'all'
|
|
28
|
+
Provides-Extra: yfinance
|
|
29
|
+
Requires-Dist: yfinance>=0.2.0; extra == 'yfinance'
|
|
30
|
+
Description-Content-Type: text/markdown
|
|
31
|
+
|
|
32
|
+
# <img src="https://raw.githubusercontent.com/botterYosuke/BackcastPro/main/docs/img/logo.drawio.svg" alt="BackcastPro Logo" width="40" height="24"> BackcastPro
|
|
33
|
+
|
|
34
|
+
トレーディング戦略のためのPythonバックテストライブラリ。
|
|
35
|
+
**リプレイ型シミュレーター**で、1バーずつ時間を進めながらチャートと売買を可視化できます。
|
|
36
|
+
|
|
37
|
+
## インストール(Windows)
|
|
38
|
+
|
|
39
|
+
### PyPIから(エンドユーザー向け)
|
|
40
|
+
|
|
41
|
+
```powershell
|
|
42
|
+
python -m pip install BackcastPro
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### 開発用インストール
|
|
46
|
+
|
|
47
|
+
```powershell
|
|
48
|
+
git clone <repository-url>
|
|
49
|
+
cd BackcastPro
|
|
50
|
+
python -m venv .venv
|
|
51
|
+
.\.venv\Scripts\Activate.ps1
|
|
52
|
+
python -m pip install -e .
|
|
53
|
+
python -m pip install -r requirements.txt
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## 使用方法
|
|
57
|
+
|
|
58
|
+
### 基本的な使い方
|
|
59
|
+
|
|
60
|
+
```python
|
|
61
|
+
from BackcastPro import Backtest
|
|
62
|
+
import pandas as pd
|
|
63
|
+
|
|
64
|
+
# データ準備
|
|
65
|
+
df = pd.read_csv("AAPL.csv", index_col=0, parse_dates=True)
|
|
66
|
+
bt = Backtest(data={"AAPL": df}, cash=100000)
|
|
67
|
+
|
|
68
|
+
# 戦略関数
|
|
69
|
+
def my_strategy(bt):
|
|
70
|
+
if bt.position == 0:
|
|
71
|
+
bt.buy(tag="entry")
|
|
72
|
+
elif bt.position > 0:
|
|
73
|
+
bt.sell(tag="exit")
|
|
74
|
+
|
|
75
|
+
# ステップ実行
|
|
76
|
+
while not bt.is_finished:
|
|
77
|
+
my_strategy(bt)
|
|
78
|
+
bt.step()
|
|
79
|
+
|
|
80
|
+
# 結果を取得
|
|
81
|
+
results = bt.finalize()
|
|
82
|
+
print(results)
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### 一括実行
|
|
86
|
+
|
|
87
|
+
```python
|
|
88
|
+
bt = Backtest(data={"AAPL": df}, cash=100000)
|
|
89
|
+
results = bt.run_with_strategy(my_strategy)
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### marimo連携(リプレイ型シミュレーター)
|
|
93
|
+
|
|
94
|
+
```python
|
|
95
|
+
import marimo as mo
|
|
96
|
+
|
|
97
|
+
slider = mo.ui.slider(start=1, stop=len(bt.index), value=1, label="時間")
|
|
98
|
+
bt.goto(slider.value, strategy=my_strategy)
|
|
99
|
+
chart = bt.chart() # plotlyローソク足 + 売買マーカー
|
|
100
|
+
|
|
101
|
+
mo.vstack([slider, chart])
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
## ドキュメント
|
|
105
|
+
|
|
106
|
+
- [ドキュメント一覧](https://github.com/botterYosuke/BackcastPro/blob/main/docs/index.md)
|
|
107
|
+
|
|
108
|
+
## バグ報告 / サポート
|
|
109
|
+
|
|
110
|
+
- バグ報告や要望は GitHub Issues へ
|
|
111
|
+
- 質問は Discord コミュニティへ([招待リンク](https://discord.gg/fzJTbpzE))
|
|
112
|
+
- 使い方はドキュメントをご参照ください
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
BackcastPro/__init__.py,sha256=vY2nk7aULUyIbW6ftJEgshANUZLSdY1l1PS0zJVfza4,1148
|
|
2
|
+
BackcastPro/_broker.py,sha256=VAHJ9A8JRxEue7bBr6RnwMOjDQy-4zPWRGFogoot6ck,20729
|
|
3
|
+
BackcastPro/_stats.py,sha256=378fs_XUyJo0etwZYnamB_69GjJFvzAmURv4fki4F9w,8260
|
|
4
|
+
BackcastPro/backtest.py,sha256=hUTJJRDkuf5R-Z0iYkdsuxXN-WxJ16osZh3IdIKCVh0,23199
|
|
5
|
+
BackcastPro/order.py,sha256=ir8FbZkWSHD1VdfWs1HlWm-xM_7zmwV4OumIK74xjIU,5545
|
|
6
|
+
BackcastPro/position.py,sha256=5yfeTJFWZdptxDkz14-IRvco13098WAWeB3A6zTQcDE,2077
|
|
7
|
+
BackcastPro/trade.py,sha256=QWISxpBNfdjNRX9K1yq-w6uLH2-E9_E0anqdWpo-2As,8113
|
|
8
|
+
BackcastPro/api/__init__.py,sha256=0sbuGUTeTsxJI9ZIJ5bL665kSh4cxO77ooojxnj0m8g,59
|
|
9
|
+
BackcastPro/api/board.py,sha256=DnzStITA2XfV6ZLW6vfPSKUxE09c0LLiWvVqCQ8oOrE,4861
|
|
10
|
+
BackcastPro/api/chart.py,sha256=-5hlOKF14xKfuouS6Ct1Hy7SG3bm1uZT7Bg48cldr54,15678
|
|
11
|
+
BackcastPro/api/db_manager.py,sha256=aKMoI6mJ0rv4NE5Zri9yh9aCIpL3oZcf5FtHTLGAHKQ,13051
|
|
12
|
+
BackcastPro/api/db_stocks_board.py,sha256=2vEn6BpDKu1mRS7eGxWMEnqa-APfea6wzfMNtm6Pa_g,18219
|
|
13
|
+
BackcastPro/api/db_stocks_daily.py,sha256=NTLrNA9-akqCU9rxRPZxHGv6SitKj2RlYvYhInP4ypo,21872
|
|
14
|
+
BackcastPro/api/db_stocks_info.py,sha256=anEI-DuA1_h1tMJItmqdkvIiCvlxVz2yQqmACKKRdrs,11029
|
|
15
|
+
BackcastPro/api/stocks_board.py,sha256=rUEno0Isy9d-AoMiPGMBF6G5FtU55VHprOs5sal4oWc,2829
|
|
16
|
+
BackcastPro/api/stocks_info.py,sha256=jU108M3MCm0bT1t1YtMJppPWaCHYgpD7A2O9YSle6Kk,3232
|
|
17
|
+
BackcastPro/api/stocks_price.py,sha256=PezgWJtVstfAFZ615S5WXHxEw8QrAxzzAQ1w_WXlPWc,5174
|
|
18
|
+
BackcastPro/api/lib/__init__.py,sha256=XbMfpIz8vom84qygXaCEUVJHhlIh9AxSa0oCkGOvgkI,50
|
|
19
|
+
BackcastPro/api/lib/e_api.py,sha256=BjYbk9beGtd1smLCpTo_ZFiM7-OZuufCz3cQjb_mG9A,23563
|
|
20
|
+
BackcastPro/api/lib/jquants.py,sha256=PCo8KlD4_Tl6HExQxpnTW-tN2XkAT6pHjRJuv20RhwQ,12826
|
|
21
|
+
BackcastPro/api/lib/kabusap.py,sha256=CoZ9FEYDcfoAbGdWhSW9V7D_EMjSJVQ8xHOARQN9kIc,9441
|
|
22
|
+
BackcastPro/api/lib/stooq.py,sha256=goPssHTORTmvkQz6Og_A-WDatZ-Bh3EikL0_9kG6dZQ,16334
|
|
23
|
+
BackcastPro/api/lib/util.py,sha256=Jwdlo9cvVVUQ9RP42VhI7C9BDXbm6N2y9539gMmwI80,950
|
|
24
|
+
backcastpro-0.3.4.dist-info/METADATA,sha256=p0zpeB4ioB85bmnUMQo1WmTw3cN_ZcO87KcS3FyCPNg,3279
|
|
25
|
+
backcastpro-0.3.4.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
26
|
+
backcastpro-0.3.4.dist-info/RECORD,,
|