Skip to content

Commit

Permalink
some clean up and plotting works again
Browse files Browse the repository at this point in the history
  • Loading branch information
97gamjak committed Apr 2, 2024
1 parent b6cce46 commit fac6c1c
Show file tree
Hide file tree
Showing 6 changed files with 362 additions and 149 deletions.
128 changes: 121 additions & 7 deletions notebooks/strategy1.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -45,20 +45,62 @@
},
{
"cell_type": "code",
"execution_count": 4,
"execution_count": 16,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
" 12%|█▏ | 58/504 [01:03<11:35, 1.56s/it]BF.B: No price data found, symbol may be delisted (1d 2012-04-05 -> 2024-04-01)\n",
" 14%|█▎ | 69/504 [01:14<08:53, 1.23s/it]BRK.B: No timezone found, symbol may be delisted\n",
" 14%|█▍ | 71/504 [01:16<08:54, 1.23s/it]"
" 0%| | 0/504 [00:00<?, ?it/s]A: No price data found, symbol may be delisted (1d 2021-04-05 -> 2024-04-02)\n",
" 12%|█▏ | 58/504 [00:12<01:51, 3.99it/s]BF.B: No price data found, symbol may be delisted (1d 2021-04-05 -> 2024-04-02)\n",
" 14%|█▎ | 69/504 [00:14<01:29, 4.86it/s]BRK.B: No timezone found, symbol may be delisted\n",
"100%|██████████| 504/504 [01:45<00:00, 4.79it/s]\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Pushing stockMarket to drive\n",
"Transferred: \t 0 B / 0 B, -, 0 B/s, ETA -\n",
"Elapsed time: 1.5sTransferred: \t 0 B / 0 B, -, 0 B/s, ETA -\n",
"Checks: 8 / 8, 100%\n",
"Elapsed time: 2.0sTransferred: \t 323.311 KiB / 323.311 KiB, 100%, 0 B/s, ETA -\n",
"Checks: 142 / 142, 100%\n",
"Transferred: 0 / 2, 0%\n",
"Elapsed time: 2.5s\n",
"Transferring:\n",
" * strategy_testing/FIB_SMA_11/.trades,json:100% /150.773Ki, 0/s, -\n",
" * strategy_testing/FIB_S…1/screening_total.xlsx:100% /172.537Ki, 0/s, -Transferred: \t 323.311 KiB / 323.311 KiB, 100%, 0 B/s, ETA -\n",
"Checks: 142 / 142, 100%\n",
"Transferred: 0 / 2, 0%\n",
"Elapsed time: 3.0s\n",
"Transferring:\n",
" * strategy_testing/FIB_SMA_11/.trades,json:100% /150.773Ki, 0/s, -\n",
" * strategy_testing/FIB_S…1/screening_total.xlsx:100% /172.537Ki, 0/s, -Transferred: \t 323.311 KiB / 323.311 KiB, 100%, 323.214 KiB/s, ETA 0s\n",
"Checks: 142 / 142, 100%\n",
"Transferred: 0 / 2, 0%\n",
"Elapsed time: 3.5s\n",
"Transferring:\n",
" * strategy_testing/FIB_SMA_11/.trades,json:100% /150.773Ki, 150.671Ki/s, 0\n",
" * strategy_testing/FIB_S…1/screening_total.xlsx:100% /172.537Ki, 172.384Ki/s,Transferred: \t 323.311 KiB / 323.311 KiB, 100%, 323.214 KiB/s, ETA 0s\n",
"Checks: 142 / 142, 100%\n",
"Transferred: 1 / 2, 50%\n",
"Elapsed time: 4.0s\n",
"Transferring:\n",
" * strategy_testing/FIB_SMA_11/.trades,json:100% /150.773Ki, 150.671Ki/s, 0Transferred: \t 323.311 KiB / 323.311 KiB, 100%, 323.214 KiB/s, ETA 0s\n",
"Checks: 142 / 142, 100%\n",
"Transferred: 2 / 2, 100%\n",
"Elapsed time: 4.1s\n",
" \n",
"*** Profile printout saved to text file 'pofile.txt'.\n"
]
}
],
"source": [
"%%prun -s cumulative -q -l 50 -T profile.txt\n",
"\n",
"import pandas as pd\n",
"import warnings\n",
"\n",
Expand All @@ -75,14 +117,14 @@
"\n",
"settings = TradeSettings(\n",
" # attached_order_type=AttachedOrderType.TRAILING_STOP_IF_TP_TOUCHED,\n",
" trailing_stop=0.00, # in percent\n",
" trailing_stop=0.02, # in percent\n",
" loss_limit=None, # in percent +- so 0.2 means 20% higher then distance to stop loss\n",
" min_PL=0.5,\n",
" max_PL=None,\n",
" min_TP_B_TC_B_to_LOW_RATIO=None,\n",
" min_ratio_high_to_ref_candle=1.03,\n",
" max_drawdown_ratio_after_new_high=0.95,\n",
" min_candles_between_TP_and_ENTRY=3,\n",
" min_candles_between_TP_and_ENTRY=1,\n",
")\n",
"\n",
"strategy = Strategy(\n",
Expand All @@ -91,7 +133,7 @@
" # [SMAStrategy([8, 20, 50]), EMAStrategy([8, 20, 50]), FIBStrategy([0.3, 0.7])],\n",
" # [EMAStrategy([8, 20, 50]), FIBStrategy([0.3, 0.7])],\n",
" # [EMAStrategy([8, 20, 50]), FIBStrategy([0.3, 0.7]), RSIStrategy(14, 60, 70)],\n",
" start_date=\"06.03.2014\",\n",
" start_date=\"06.03.2023\",\n",
" end_date=\"05.03.2024\",\n",
" candle_period=\"weekly\",\n",
" base_path=\"/home/jag/rclone/drive/stockMarket/Trading/strategy_testing\",\n",
Expand All @@ -108,6 +150,78 @@
" strategy.screen(tickers)"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
" 99491680 function calls (97846087 primitive calls) in 111.245 seconds\n",
"\n",
" Ordered by: cumulative time\n",
" List reduced from 2962 to 50 due to restriction <50>\n",
"\n",
" ncalls tottime percall cumtime percall filename:lineno(function)\n",
" 1 0.000 0.000 111.252 111.252 {built-in method builtins.exec}\n",
" 1 0.001 0.001 111.252 111.252 <string>:1(<module>)\n",
" 1072/1 0.003 0.000 111.249 111.249 decorator.py:229(fun)\n",
" 1 0.000 0.000 111.249 111.249 _common.py:7(finalize)\n",
" 1 0.028 0.028 107.047 107.047 strategy.py:222(screen)\n",
" 504 0.032 0.000 89.579 0.178 strategy.py:241(populate_pricing_data)\n",
" 504 0.005 0.000 67.524 0.134 _common.py:55(get_daily_candle_range)\n",
" 2014/504 0.046 0.000 67.295 0.134 utils.py:98(wrapper)\n",
" 504 0.243 0.000 67.241 0.133 base.py:84(history)\n",
" 503 0.009 0.000 58.061 0.115 data.py:332(get)\n",
" 503 0.003 0.000 58.034 0.115 sessions.py:593(get)\n",
" 503 0.006 0.000 58.030 0.115 sessions.py:502(request)\n",
" 503 0.011 0.000 56.939 0.113 sessions.py:673(send)\n",
" 4117 0.009 0.000 55.893 0.014 socket.py:692(readinto)\n",
" 4117 0.014 0.000 55.879 0.014 ssl.py:1299(recv_into)\n",
" 4117 0.006 0.000 55.863 0.014 ssl.py:1157(read)\n",
" 4117 55.857 0.014 55.857 0.014 {method 'read' of '_ssl._SSLSocket' objects}\n",
" 11034 0.009 0.000 51.393 0.005 {method 'readline' of '_io.BufferedReader' objects}\n",
" 503 0.008 0.000 50.460 0.100 adapters.py:434(send)\n",
" 503 0.013 0.000 50.258 0.100 connectionpool.py:534(urlopen)\n",
" 503 0.011 0.000 50.078 0.100 connectionpool.py:379(_make_request)\n",
" 503 0.003 0.000 49.866 0.099 client.py:1346(getresponse)\n",
" 503 0.009 0.000 49.852 0.099 client.py:318(begin)\n",
" 503 0.009 0.000 49.687 0.099 client.py:285(_read_status)\n",
" 504 0.015 0.000 19.056 0.038 fibStrategy.py:22(calculate_indicators)\n",
" 504 0.003 0.000 18.993 0.038 frame.py:9411(apply)\n",
" 504 0.074 0.000 18.986 0.038 apply.py:731(apply)\n",
" 501 0.002 0.000 18.908 0.038 apply.py:890(apply_standard)\n",
" 504 0.279 0.001 15.293 0.030 strategy.py:282(_screen_single_ticker)\n",
" 501 0.156 0.000 13.816 0.028 apply.py:896(apply_series_generator)\n",
" 297060 0.328 0.000 11.950 0.000 indexing.py:1059(__getitem__)\n",
" 294196 0.668 0.000 10.833 0.000 indexing.py:1592(_getitem_axis)\n",
" 78138 0.119 0.000 10.451 0.000 fibStrategy.py:23(apply_candle_body_outside_range)\n",
" 26463 0.027 0.000 10.299 0.000 strategy.py:306(<listcomp>)\n",
" 52926 0.090 0.000 10.272 0.000 _base.py:36(evaluate_rules)\n",
"353772/350814 0.913 0.000 9.633 0.000 series.py:342(__init__)\n",
" 92573 0.326 0.000 8.044 0.000 frame.py:3703(_ixs)\n",
" 14799 0.045 0.000 7.210 0.000 frame.py:609(__init__)\n",
" 3071 0.034 0.000 6.865 0.002 construction.py:423(dict_to_mgr)\n",
" 2512 0.003 0.000 6.449 0.003 models.py:887(content)\n",
" 5531 0.006 0.000 6.447 0.001 {method 'join' of 'bytes' objects}\n",
" 1878 0.003 0.000 6.441 0.003 models.py:812(generate)\n",
" 1878 0.002 0.000 6.438 0.003 response.py:607(stream)\n",
" 1874 0.011 0.000 6.435 0.003 response.py:789(read_chunked)\n",
" 3515 0.012 0.000 5.645 0.002 construction.py:100(arrays_to_mgr)\n",
" 52926 0.112 0.000 5.204 0.000 _base.py:51(_evaluate_bullish_rules)\n",
" 501 0.003 0.000 5.090 0.010 apply.py:915(wrap_results)\n",
" 501 0.001 0.000 5.079 0.010 apply.py:1050(wrap_results_for_axis)\n",
" 501 0.004 0.000 5.077 0.010 apply.py:1071(infer_to_same_shape)\n",
" 52926 0.092 0.000 4.972 0.000 _base.py:58(_evaluate_bearish_rules)\n"
]
}
],
"source": [
"print(open(\"profile.txt\", \"r\").read())"
]
},
{
"cell_type": "code",
"execution_count": null,
Expand Down
113 changes: 85 additions & 28 deletions stockMarket/technicalAnalysis/plotter/strategyPlotter.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,28 +40,40 @@ def plot_PL_histogram(self,
if trade.outcome_status == TradeOutcome.LOSS
]

# Calculate the counts of win and loss PL values in each bin
win_PL_per_bin, _ = np.histogram(win_PL)
loss_PL_per_bin, _ = np.histogram(loss_PL)
win_PL = np.array(win_PL)
loss_PL = np.array(loss_PL)

# create 2d numpy array of win and loss PL values for each bin
win_PL_indices = np.digitize(win_PL, bins) - 1
loss_PL_indices = np.digitize(loss_PL, bins) - 1

win_PL_per_bin = [win_PL[win_PL_indices == i]
for i in range(0, len(bins))]
loss_PL_per_bin = [loss_PL[loss_PL_indices == i]
for i in range(0, len(bins))]

amount_wins_per_bin = np.array([len(win_PL_per_bin[i])
for i in range(0, len(bins))])
amount_losses_per_bin = np.array([len(loss_PL_per_bin[i])
for i in range(0, len(bins))])

# Calculate the total number of trades in each bin
total_trades_per_bin = win_PL_per_bin + loss_PL_per_bin
total_trades_per_bin = amount_wins_per_bin + amount_losses_per_bin

# Calculate the effective and theoretical PL ratio for each bin
PL_ratio_effective = np.zeros_like(win_PL_per_bin, dtype=float)
PL_ratio_effective = np.zeros_like(amount_wins_per_bin, dtype=float)
np.true_divide(
win_PL_per_bin,
amount_wins_per_bin,
total_trades_per_bin,
out=PL_ratio_effective,
where=total_trades_per_bin != 0,
)
PL_ratio_theoretical = np.mean(
np.concatenate((win_PL_per_bin, loss_PL_per_bin)),
axis=1
)

print(PL_ratio_theoretical)
print(PL_ratio_effective)
PL_ratio_theoretical = []
for win, loss in zip(win_PL_per_bin, loss_PL_per_bin):
PL_ratio_theoretical.append(np.mean(np.concatenate([win, loss])))

PL_ratio_theoretical = np.array(PL_ratio_theoretical)

# Create a figure and a subplot
_, ax1 = plt.subplots()
Expand Down Expand Up @@ -97,10 +109,37 @@ def plot_PL_histogram(self,
@finalize
def plot_trades_vs_time(self, max_loss: float = 1.0):

trade_data = [
(
trade.INVESTMENT,
trade.OUTCOME,
trade.trade_status,
trade.EXIT_date,
trade.ENTRY_date
)
for trade in self.trades
]

# Create a DataFrame from the trades
trades_df = pd.DataFrame(self.trades)
trades_df = pd.DataFrame(
trade_data,
columns=['INVESTMENT',
'OUTCOME',
'trade_status',
'EXIT_date',
'ENTRY_date'
]
)
trades_df['INVESTMENT'] = trades_df['INVESTMENT'] * max_loss
trades_df['OUTCOME'] = trades_df['OUTCOME'] * max_loss
trades_df['INVESTMENT'] = trades_df['INVESTMENT'] * max_loss
trades_df['OUTCOME'] = trades_df['OUTCOME'] * max_loss
trades_df = trades_df.dropna(subset=['ENTRY_date'])

executed_trades = trades_df[
(trades_df['trade_status'] == TradeStatus.OPEN) |
(trades_df['trade_status'] == TradeStatus.CLOSED)
]

# Set the date range
date_range = pd.date_range(
Expand All @@ -116,22 +155,39 @@ def plot_trades_vs_time(self, max_loss: float = 1.0):
result_df['total_outcome'] = 0.0

# Calculate the total outcome for closed trades
closed_trades = trades_df[trades_df.trade_status == TradeStatus.CLOSED]
result_df.loc[closed_trades.EXIT_date,
'total_outcome'] += (closed_trades.OUTCOME).values

# Calculate the amount of trades and total invested for open trades and trades that have not exited yet
open_trades = trades_df[
(trades_df.trade_status == TradeStatus.OPEN) |
(trades_df.EXIT_date >= result_df.index)
closed_trades = trades_df[
trades_df.trade_status == TradeStatus.CLOSED
]
result_df.loc[open_trades.ENTRY_date, 'amount_trades'] += 1
result_df.loc[open_trades.ENTRY_date,
'total_invested'] += (open_trades.INVESTMENT).values
result_df.loc[
closed_trades.EXIT_date,
'total_outcome'
] += (closed_trades.OUTCOME).values

# Forward fill the result DataFrame to propagate the last valid observation forward to the next valid
result_df.ffill()

# calculate amount trades where trade_status is open or EXIT_date is larger than the date index of result_df and trade_status is closed
def update_result(row):
date = row.name
df = executed_trades.copy()
df = df.drop(df[df['ENTRY_date'] > date].index)

relevant_trades = df[df['EXIT_date'].isnull()]
df = df.drop(relevant_trades.index)

relevant_trades = pd.concat(
[
relevant_trades,
df[df['EXIT_date'] > date]
]
)

row['amount_trades'] = len(relevant_trades)
row['total_invested'] = relevant_trades['INVESTMENT'].sum()
return row

result_df = result_df.apply(update_result, axis=1)

max_edit_date = result_df[result_df['amount_trades'] != 0].index.max()
result_df = result_df[:max_edit_date]

Expand All @@ -141,10 +197,11 @@ def plot_trades_vs_time(self, max_loss: float = 1.0):
ax[0].set_xlabel("Date", fontsize=18)
ax[0].set_ylabel("Amount of trades", fontsize=18)

ax[1].plot(result_df.index,
np.cumsum(result_df['total_invested']),
color="r"
)
ax[1].plot(
result_df.index,
result_df['total_invested'],
color="r"
)
ax[1].set_ylabel("Total Invested in $", fontsize=18)
ax[1].set_xlabel("Date", fontsize=18)

Expand Down
Loading

0 comments on commit fac6c1c

Please sign in to comment.