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

BackcastPro/backtest.py CHANGED
@@ -76,8 +76,9 @@ class Backtest:
76
76
  まだ[アクティブで継続中]の取引は最後のバーでクローズされ、
77
77
  計算されたバックテスト統計に貢献します。
78
78
  """
79
+
79
80
  def __init__(self,
80
- data: pd.DataFrame,
81
+ data: dict[str, pd.DataFrame],
81
82
  strategy: Type,
82
83
  *,
83
84
  cash: float = 10_000,
@@ -94,8 +95,7 @@ class Backtest:
94
95
 
95
96
  if not (isinstance(strategy, type) and issubclass(strategy, Strategy)):
96
97
  raise TypeError('`strategy` must be a Strategy sub-type')
97
- if not isinstance(data, pd.DataFrame):
98
- raise TypeError("`data` must be a pandas.DataFrame with columns")
98
+
99
99
  if not isinstance(spread, Number):
100
100
  raise TypeError('`spread` must be a float value, percent of '
101
101
  'entry order price')
@@ -105,47 +105,63 @@ class Backtest:
105
105
  'or a function that takes `(order_size, price)`'
106
106
  'and returns commission dollar value')
107
107
 
108
- data = data.copy(deep=False)
109
-
110
- # インデックスをdatetimeインデックスに変換
111
- if (not isinstance(data.index, pd.DatetimeIndex) and
112
- not isinstance(data.index, pd.RangeIndex) and
113
- # 大部分が大きな数値の数値インデックス
114
- (data.index.is_numeric() and
115
- (data.index > pd.Timestamp('1975').timestamp()).mean() > .8)):
116
- try:
117
- data.index = pd.to_datetime(data.index, infer_datetime_format=True)
118
- except ValueError:
119
- pass
120
-
121
- if 'Volume' not in data:
122
- data['Volume'] = np.nan
123
-
124
- if len(data) == 0:
125
- raise ValueError('OHLC `data` is empty')
126
- if len(data.columns.intersection({'Open', 'High', 'Low', 'Close', 'Volume'})) != 5:
127
- raise ValueError("`data` must be a pandas.DataFrame with columns "
128
- "'Open', 'High', 'Low', 'Close', and (optionally) 'Volume'")
129
- if data[['Open', 'High', 'Low', 'Close']].isnull().values.any():
130
- raise ValueError('Some OHLC values are missing (NaN). '
131
- 'Please strip those lines with `df.dropna()` or '
132
- 'fill them in with `df.interpolate()` or whatever.')
133
- if np.any(data['Close'] > cash):
134
- warnings.warn('Some prices are larger than initial cash value. Note that fractional '
135
- 'trading is not supported by this class. If you want to trade Bitcoin, '
136
- 'increase initial cash, or trade μBTC or satoshis instead (see e.g. class '
137
- '`backtesting.lib.FractionalBacktest`.',
138
- stacklevel=2)
139
- if not data.index.is_monotonic_increasing:
140
- warnings.warn('Data index is not sorted in ascending order. Sorting.',
141
- stacklevel=2)
142
- data = data.sort_index()
143
- if not isinstance(data.index, pd.DatetimeIndex):
144
- warnings.warn('Data index is not datetime. Assuming simple periods, '
145
- 'but `pd.DateTimeIndex` is advised.',
146
- stacklevel=2)
147
-
148
- self._data: pd.DataFrame = data
108
+ k0, v0 = next(iter(data.items()))
109
+ len0 = len(v0)
110
+ for k, v in list(data.items())[1:]:
111
+ if not len0 == len(v):
112
+ raise TypeError(f"`data[{k}]` 数が、{k0}と合致していません。")
113
+
114
+
115
+ data = data.copy()
116
+
117
+ for code, df in data.items():
118
+ if not isinstance(df, pd.DataFrame):
119
+ raise TypeError(f"`data[{code}]` must be a pandas.DataFrame with columns")
120
+
121
+ # インデックスをdatetimeインデックスに変換
122
+ if (not isinstance(df.index, pd.DatetimeIndex) and
123
+ not isinstance(df.index, pd.RangeIndex) and
124
+ # 大部分が大きな数値の数値インデックス
125
+ (df.index.is_numeric() and
126
+ (df.index > pd.Timestamp('1975').timestamp()).mean() > .8)):
127
+ try:
128
+ df.index = pd.to_datetime(df.index, infer_datetime_format=True)
129
+ except ValueError:
130
+ pass
131
+
132
+ if 'Volume' not in df:
133
+ df['Volume'] = np.nan
134
+
135
+ if len(df) == 0:
136
+ raise ValueError(f'OHLC `data[{code}]` is empty')
137
+ if len(df.columns.intersection({'Open', 'High', 'Low', 'Close', 'Volume'})) != 5:
138
+ raise ValueError(f"`data[{code}]` must be a pandas.DataFrame with columns "
139
+ "'Open', 'High', 'Low', 'Close', and (optionally) 'Volume'")
140
+ if df[['Open', 'High', 'Low', 'Close']].isnull().values.any():
141
+ raise ValueError('Some OHLC values are missing (NaN). '
142
+ 'Please strip those lines with `df.dropna()` or '
143
+ 'fill them in with `df.interpolate()` or whatever.')
144
+ if np.any(df['Close'] > cash):
145
+ warnings.warn('Some prices are larger than initial cash value. Note that fractional '
146
+ 'trading is not supported by this class. If you want to trade Bitcoin, '
147
+ 'increase initial cash, or trade μBTC or satoshis instead (see e.g. class '
148
+ '`backtesting.lib.FractionalBacktest`.',
149
+ stacklevel=2)
150
+ if not df.index.is_monotonic_increasing:
151
+ warnings.warn(f'data[{code}] index is not sorted in ascending order. Sorting.',
152
+ stacklevel=2)
153
+ df = df.sort_index()
154
+ data[code] = df # 重要:ソート後のDataFrameを辞書に再代入
155
+ if not isinstance(df.index, pd.DatetimeIndex):
156
+ warnings.warn(f'data[{code}] index is not datetime. Assuming simple periods, '
157
+ 'but `pd.DateTimeIndex` is advised.',
158
+ stacklevel=2)
159
+
160
+ # 辞書dataに含まれる全てのdf.index一覧を作成
161
+ # df.indexが不一致の場合のために、どれかに固有値があれば抽出しておくため
162
+ self.index: pd.DatetimeIndex = pd.DatetimeIndex(sorted({idx for df in data.values() for idx in df.index}))
163
+
164
+ self._data: dict[str, pd.DataFrame] = data
149
165
 
150
166
  # partialとは、関数の一部の引数を事前に固定して、新しい関数を作成します。
151
167
  # これにより、後で残りの引数だけを渡せば関数を実行できるようになります。
@@ -155,16 +171,13 @@ class Backtest:
155
171
  self._broker = partial(
156
172
  _Broker, cash=cash, spread=spread, commission=commission, margin=margin,
157
173
  trade_on_close=trade_on_close, hedging=hedging,
158
- exclusive_orders=exclusive_orders, index=data.index,
174
+ exclusive_orders=exclusive_orders
159
175
  )
160
176
 
161
177
  self._strategy = strategy
162
178
  self._results: Optional[pd.Series] = None
163
179
  self._finalize_trades = bool(finalize_trades)
164
180
 
165
- # 初期化パラメータを保存(実行後に振り返るため)
166
- self._cash = cash
167
- self._commission = commission
168
181
 
169
182
  def run(self) -> pd.Series:
170
183
  """
@@ -219,49 +232,50 @@ class Backtest:
219
232
  # 循環インポートを避けるためにここでインポート
220
233
  from .strategy import Strategy
221
234
 
222
- data = self._data.copy(deep=False)
223
- broker: _Broker = self._broker(data=data)
224
- strategy: Strategy = self._strategy(broker, data)
235
+ broker: _Broker = self._broker(data=self._data)
236
+ strategy: Strategy = self._strategy(broker, self._data)
225
237
 
226
238
  strategy.init()
227
239
 
228
- # strategy.init()で加工されたdataを再登録
229
- self._data = data
240
+ # strategy.init()で加工されたdataを登録
241
+ data = self._data.copy()
230
242
 
231
- # インジケーターがまだ「ウォームアップ」中の最初の数本のキャンドルをスキップ
232
- # 少なくとも2つのエントリが利用可能になるように+1
233
- start = 1
234
-
235
243
  # "invalid value encountered in ..."警告を無効化。比較
236
244
  # np.nan >= 3は無効ではない;Falseです。
237
245
  with np.errstate(invalid='ignore'):
238
246
 
239
247
  # プログレスバーを表示
240
- progress_bar = tqdm(range(start, len(self._data)),
248
+ progress_bar = tqdm(self.index,
241
249
  desc="バックテスト実行中",
242
250
  unit="step",
243
251
  ncols=120,
244
252
  leave=True,
245
253
  dynamic_ncols=True)
246
-
247
- for i in progress_bar:
254
+ count = 0
255
+ for current_time in progress_bar:
256
+
248
257
  # 注文処理とブローカー関連の処理
249
- data = self._data.iloc[:i]
258
+ for k, value in self._data.items():
259
+ # time以前のデータをフィルタリング
260
+ data[k] = value[value.index <= current_time]
261
+
262
+ # brokerに更新したdateを再登録
250
263
  try:
251
264
  broker._data = data
252
- broker.next()
265
+ broker.next(current_time)
253
266
  except:
254
267
  break
255
268
 
256
269
  # 次のティック、バークローズ直前
257
270
  strategy._data = data
258
- strategy.next()
271
+ strategy.next(current_time)
259
272
 
273
+ count += 1
274
+
260
275
  # プログレスバーの説明を更新(現在の日付を表示)
261
- if hasattr(self._data.index, 'strftime') and i > 0:
276
+ if data:
262
277
  try:
263
- current_date = self._data.index[i-1].strftime('%Y-%m-%d')
264
- progress_bar.set_postfix({"日付": current_date})
278
+ progress_bar.set_postfix({"日付": current_time.strftime('%Y-%m-%d')})
265
279
  except:
266
280
  pass
267
281
  else:
@@ -272,8 +286,7 @@ class Backtest:
272
286
 
273
287
  # HACK: 最後の戦略イテレーションで配置されたクローズ注文を処理するために
274
288
  # ブローカーを最後にもう一度実行。最後のブローカーイテレーションと同じOHLC値を使用。
275
- if start < len(self._data):
276
- broker.next()
289
+ broker.next(self.index[count-1])
277
290
  elif len(broker.trades):
278
291
  warnings.warn(
279
292
  'バックテスト終了時に一部の取引がオープンのままです。'
@@ -283,11 +296,22 @@ class Backtest:
283
296
  equity = pd.Series(broker._equity).bfill().fillna(broker._cash).values
284
297
  self._results = compute_stats(
285
298
  trades=broker.closed_trades,
286
- equity=equity,
287
- ohlc_data=self._data,
299
+ equity=np.array(equity),
300
+ index=self.index,
288
301
  strategy_instance=strategy,
289
302
  risk_free_rate=0.0,
290
303
  )
291
304
 
292
305
  return self._results
293
306
 
307
+
308
+ @property
309
+ def cash(self):
310
+ # partialで初期化されている場合、初期化時のcash値を返す
311
+ return self._broker.keywords.get('cash', 0)
312
+
313
+
314
+ @property
315
+ def commission(self):
316
+ # partialで初期化されている場合、初期化時のcommission値を返す
317
+ return self._broker.keywords.get('commission', 0)
BackcastPro/order.py CHANGED
@@ -21,7 +21,9 @@ class Order:
21
21
 
22
22
  すべての出された注文は[取消注文まで有効]です。
23
23
  """
24
+
24
25
  def __init__(self, broker: '_Broker',
26
+ code: str,
25
27
  size: float,
26
28
  limit_price: Optional[float] = None,
27
29
  stop_price: Optional[float] = None,
@@ -29,6 +31,7 @@ class Order:
29
31
  tp_price: Optional[float] = None,
30
32
  parent_trade: Optional['Trade'] = None,
31
33
  tag: object = None):
34
+ self.__code = code
32
35
  self.__broker = broker
33
36
  assert size != 0
34
37
  self.__size = size
@@ -59,6 +62,13 @@ class Order:
59
62
 
60
63
  # Fields getters
61
64
 
65
+ @property
66
+ def code(self) -> str:
67
+ """
68
+ 注文対象の銘柄コード。
69
+ """
70
+ return self.__code
71
+
62
72
  @property
63
73
  def size(self) -> float:
64
74
  """
BackcastPro/position.py CHANGED
@@ -18,6 +18,7 @@ class Position:
18
18
  if self.position:
19
19
  ... # ポジションがあります(ロングまたはショート)
20
20
  """
21
+
21
22
  def __init__(self, broker: '_Broker'):
22
23
  self.__broker = broker
23
24
 
@@ -57,5 +58,3 @@ class Position:
57
58
  for trade in self.__broker.trades:
58
59
  trade.close(portion)
59
60
 
60
- def __repr__(self):
61
- return f'<Position: {self.size} ({len(self.__broker.trades)} trades)>'
BackcastPro/strategy.py CHANGED
@@ -6,6 +6,7 @@ from __future__ import annotations
6
6
 
7
7
  import sys
8
8
  from abc import ABCMeta, abstractmethod
9
+ from tkinter import NO
9
10
  from typing import Optional, Tuple
10
11
 
11
12
  import pandas as pd
@@ -35,12 +36,12 @@ class Strategy(metaclass=ABCMeta):
35
36
  オーバーライドして独自の戦略を定義してください。
36
37
  """
37
38
 
38
- def __init__(self, broker: _Broker, data: pd.DataFrame):
39
+ def __init__(self, broker: _Broker, data: dict[str, pd.DataFrame]):
39
40
  """
40
41
  これは Backtestクラスで初期化するためユーザーは不要
41
42
  """
42
43
  self._broker: _Broker = broker
43
- self._data: pd.DataFrame = data
44
+ self._data: dict[str, pd.DataFrame] = data
44
45
 
45
46
 
46
47
  @abstractmethod
@@ -58,7 +59,7 @@ class Strategy(metaclass=ABCMeta):
58
59
  """
59
60
 
60
61
  @abstractmethod
61
- def next(self):
62
+ def next(self, current_time: pd.Timestamp):
62
63
  """
63
64
  メインのストラテジー実行メソッド。新しい
64
65
  `backtesting.backtesting.Strategy.data`
@@ -88,6 +89,7 @@ class Strategy(metaclass=ABCMeta):
88
89
  _FULL_EQUITY = __FULL_EQUITY(1 - sys.float_info.epsilon)
89
90
 
90
91
  def buy(self, *,
92
+ code: str,
91
93
  size: float = _FULL_EQUITY,
92
94
  limit: Optional[float] = None,
93
95
  stop: Optional[float] = None,
@@ -108,9 +110,11 @@ class Strategy(metaclass=ABCMeta):
108
110
  """
109
111
  assert 0 < size < 1 or round(size) == size >= 1, \
110
112
  "sizeは正の資産割合または正の整数単位である必要があります"
111
- return self._broker.new_order(size, limit, stop, sl, tp, tag)
113
+
114
+ return self._broker.new_order(code, size, limit, stop, sl, tp, tag)
112
115
 
113
116
  def sell(self, *,
117
+ code: str,
114
118
  size: float = _FULL_EQUITY,
115
119
  limit: Optional[float] = None,
116
120
  stop: Optional[float] = None,
@@ -139,7 +143,8 @@ class Strategy(metaclass=ABCMeta):
139
143
  """
140
144
  assert 0 < size < 1 or round(size) == size >= 1, \
141
145
  "sizeは正の資産割合または正の整数単位である必要があります"
142
- return self._broker.new_order(-size, limit, stop, sl, tp, tag)
146
+
147
+ return self._broker.new_order(code, -size, limit, stop, sl, tp, tag)
143
148
 
144
149
  @property
145
150
  def equity(self) -> float:
@@ -147,7 +152,7 @@ class Strategy(metaclass=ABCMeta):
147
152
  return self._broker.equity
148
153
 
149
154
  @property
150
- def data(self) -> pd.DataFrame:
155
+ def data(self) -> dict[str, pd.DataFrame]:
151
156
  """
152
157
  価格データは、`Backtest.__init__`に渡されるものと同じ
153
158
  """
@@ -172,3 +177,4 @@ class Strategy(metaclass=ABCMeta):
172
177
  def closed_trades(self) -> 'Tuple[Trade, ...]':
173
178
  """決済済みトレードリスト(`Trade` を参照)。"""
174
179
  return tuple(self._broker.closed_trades)
180
+
BackcastPro/trade.py CHANGED
@@ -18,23 +18,19 @@ class Trade:
18
18
  `Order`が約定されると、アクティブな`Trade`が発生します。
19
19
  アクティブな取引は`Strategy.trades`で、クローズされた決済済み取引は`Strategy.closed_trades`で見つけることができます。
20
20
  """
21
- def __init__(self, broker: '_Broker', size: int, entry_price: float, entry_bar, tag):
21
+ def __init__(self, broker: '_Broker', code: str, size: int, entry_price: float, entry_time: Union[pd.Timestamp, int], tag):
22
22
  self.__broker = broker
23
+ self.__code = code
23
24
  self.__size = size
24
25
  self.__entry_price = entry_price
25
26
  self.__exit_price: Optional[float] = None
26
- self.__entry_bar: int = entry_bar
27
- self.__exit_bar: Optional[int] = None
27
+ self.__entry_time: Union[pd.Timestamp, int] = entry_time
28
+ self.__exit_time: Optional[Union[pd.Timestamp, int]] = None
28
29
  self.__sl_order: Optional[Order] = None
29
30
  self.__tp_order: Optional[Order] = None
30
31
  self.__tag = tag
31
32
  self._commissions = 0
32
33
 
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
34
  def _replace(self, **kwargs):
39
35
  for k, v in kwargs.items():
40
36
  setattr(self, f'_{self.__class__.__qualname__}__{k}', v)
@@ -49,11 +45,16 @@ class Trade:
49
45
  # Ensure size is an int to avoid rounding errors on 32-bit OS
50
46
  size = copysign(max(1, int(round(abs(self.__size) * portion))), -self.__size)
51
47
  from .order import Order
52
- order = Order(self.__broker, size, parent_trade=self, tag=self.__tag)
48
+ order = Order(self.__broker, self.__code, size, parent_trade=self, tag=self.__tag)
53
49
  self.__broker.orders.insert(0, order)
54
50
 
55
51
  # Fields getters
56
52
 
53
+ @property
54
+ def code(self):
55
+ """取引対象銘柄"""
56
+ return self.__code
57
+
57
58
  @property
58
59
  def size(self):
59
60
  """取引サイズ(ボリューム;ショート取引の場合は負の値)。"""
@@ -71,16 +72,59 @@ class Trade:
71
72
 
72
73
  @property
73
74
  def entry_bar(self) -> int:
74
- """取引がエントリーされた時のローソク足バーのインデックス。"""
75
- return self.__entry_bar
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
76
94
 
77
95
  @property
78
96
  def exit_bar(self) -> Optional[int]:
79
97
  """
80
98
  取引がエグジットされた時のローソク足バーのインデックス
81
99
  (取引がまだアクティブな場合はNone)。
100
+
101
+ .. deprecated:: 0.1.0
102
+ `exit_time`プロパティを使用してください。
82
103
  """
83
- return self.__exit_bar
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
84
128
 
85
129
  @property
86
130
  def tag(self):
@@ -103,18 +147,6 @@ class Trade:
103
147
 
104
148
  # Extra properties
105
149
 
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
150
  @property
119
151
  def is_long(self):
120
152
  """取引がロングの場合True(取引サイズが正の値)。"""
@@ -131,13 +163,13 @@ class Trade:
131
163
  取引の利益(正の値)または損失(負の値)を現金単位で表示。
132
164
  手数料は取引がクローズされた後にのみ反映されます。
133
165
  """
134
- price = self.__exit_price or self.__broker.last_price
166
+ price = self.__exit_price or self.__broker.last_price(self.__code)
135
167
  return (self.__size * (price - self.__entry_price)) - self._commissions
136
168
 
137
169
  @property
138
170
  def pl_pct(self):
139
171
  """取引の利益(正の値)または損失(負の値)をパーセントで表示。"""
140
- price = self.__exit_price or self.__broker.last_price
172
+ price = self.__exit_price or self.__broker.last_price(self.__code)
141
173
  gross_pl_pct = copysign(1, self.__size) * (price / self.__entry_price - 1)
142
174
 
143
175
  # 取引全体のサイズに対する手数料を個別単位に換算
@@ -147,7 +179,7 @@ class Trade:
147
179
  @property
148
180
  def value(self):
149
181
  """取引の総価値を現金単位で表示(ボリューム × 価格)。"""
150
- price = self.__exit_price or self.__broker.last_price
182
+ price = self.__exit_price or self.__broker.last_price(self.__code)
151
183
  return abs(self.__size) * price
152
184
 
153
185
  # SL/TP management API
@@ -191,5 +223,5 @@ class Trade:
191
223
  order.cancel()
192
224
  if price:
193
225
  kwargs = {'stop': price} if type == 'sl' else {'limit': price}
194
- order = self.__broker.new_order(-self.size, trade=self, tag=self.tag, **kwargs)
226
+ order = self.__broker.new_order(self.code, -self.size, trade=self, tag=self.tag, **kwargs)
195
227
  setattr(self, attr, order)
@@ -1,11 +1,11 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: BackcastPro
3
- Version: 0.0.5
3
+ Version: 0.1.1
4
4
  Summary: トレーディング戦略のためのPythonバックテストライブラリ
5
- Author-email: botterYosuke <yosuke.sasazawa@gmail.com>
5
+ Author: botterYosuke
6
6
  Project-URL: Homepage, https://github.com/botterYosuke/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.drawio.svg
7
+ Project-URL: Issues, https://github.com/botterYosuke/BackcastPro/issues
8
+ Project-URL: Logo, https://raw.githubusercontent.com/botterYosuke/BackcastPro/main/docs/img/logo.drawio.svg
9
9
  Classifier: Programming Language :: Python :: 3
10
10
  Classifier: Operating System :: OS Independent
11
11
  Classifier: License :: OSI Approved :: MIT License
@@ -45,7 +45,6 @@ py -m pip install -r requirements.txt
45
45
 
46
46
  ```python
47
47
  from BackcastPro import Strategy, Backtest
48
- from BackcastPro.data import DataReader, JapanStocks
49
48
 
50
49
  # ここにトレーディング戦略の実装を記述
51
50
  ```
@@ -0,0 +1,12 @@
1
+ BackcastPro/__init__.py,sha256=VS0jRp1UqgrHufWzx_mq_TuULtoX_DSxwEOXp2by4tQ,870
2
+ BackcastPro/_broker.py,sha256=KaZUxCisbB_5RRMSpIGhus3-gTurgZK-ETd7eo3JANo,20562
3
+ BackcastPro/_stats.py,sha256=swVWo2ZEP7Qt_neVuEXBw9GbshLU28oc4EyPedW3XlI,8437
4
+ BackcastPro/backtest.py,sha256=nI-X7DKSIahiJf3PTWjwjvc8qG7pt6FNDCgrhR9nKYY,15952
5
+ BackcastPro/order.py,sha256=S_2j6zjSFNgujJJDcaQw1-cXU9jgwE-PTCMLZvx6EAI,5706
6
+ BackcastPro/position.py,sha256=xm8umqpJDHqLEmQ_qyq_K0VR1rKO6mY2J10c0wlzYCU,2137
7
+ BackcastPro/strategy.py,sha256=zHCYMjfE6RA4Y-ANvGBp7dEpxFsSbSzf4Vtv1vN0jc8,7359
8
+ BackcastPro/trade.py,sha256=fXB2YKdDzgnc895-PGdad2_sh5uH6X6HoEeFpD5CeCc,8340
9
+ backcastpro-0.1.1.dist-info/METADATA,sha256=NnynVoy3YDAEIY8E4rYuLrcom0dmOpNk-xX9wLcL2_Q,2061
10
+ backcastpro-0.1.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
11
+ backcastpro-0.1.1.dist-info/top_level.txt,sha256=GiP-TX_Bc2jjwHS9cx0VCrW27e9JPbhWWnqGxa5B4Fs,12
12
+ backcastpro-0.1.1.dist-info/RECORD,,