Skip to content

Commit e3c0535

Browse files
committed
feat: bca doc
1 parent dfc2ebd commit e3c0535

File tree

1 file changed

+176
-12
lines changed

1 file changed

+176
-12
lines changed

Diff for: blog/2023-07-19-bca.mdx

+176-12
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
slug: bca
3-
title: ACE X CA X Lead Capital 量化課程 7/19
3+
title: ACE X CA X Lead Capital 量化課程
44
author: BCA Daniel
55
author_title: Quant Lead & BD & MM
66
author_url: https://www.instagram.com/bca_daniel_/
@@ -9,18 +9,66 @@ hide_table_of_contents: false
99
tags: [quant, tradingview, python, ema]
1010
---
1111

12+
13+
<details>
14+
<summary>此頁的QR連結</summary>
15+
<img src="/img/blog/aceqr.png" width="60%"/>
16+
</details>
17+
18+
<details>
19+
<summary>課綱</summary>
20+
<img src="/img/blog/ace791.JPG" width="50%"/>
21+
<img src="/img/blog/ace726.JPG" width="50%"/>
22+
</details>
23+
24+
1225
### `Crypto-Arsenal`
1326

1427

1528
- [註冊連結](https://crypto-arsenal.io/?ref=BCA_qbb) (可以 Google 註冊)
16-
29+
- 如何用CA串接和自動化任何 `TradingView` 策略: 到 [Strategy](https://crypto-arsenal.io/strategies) > `New Strategy` > `TradingView` ([詳細教學](https://docs.crypto-arsenal.io/docs/tradingview/strategy/sync-by-position))
30+
- 如何用CA回測和實單策略: 到 [Strategy](https://crypto-arsenal.io/strategies) > `New Strategy` > `Technical Indicator` > `EMA`
1731

1832
### `TradingView`
1933

34+
#### 7/26 簡易`EMA`策略 + 簡易 Filter (濾網) i.e `RSI` & `Momentum`
2035

21-
- [TradingView CA ema cross 策略](https://www.tradingview.com/script/P31Kg8mq/)
36+
```python
37+
//@version=5
38+
strategy(title="CA_test", shorttitle="EMA", overlay=true, default_qty_value = 80)
39+
40+
ema10 = ta.ema(close,10)
41+
ema20 = ta.ema(close,20)
42+
//filter
43+
rsi = ta.rsi(close,20)
44+
mom = math.abs( ta.mom(close,49) )
45+
46+
//condition
47+
long = ta.crossover(ema10,ema20)
48+
short = ta.crossunder(ema10,ema20)
49+
50+
//position
51+
if(long and mom >= 10 and rsi < 50)
52+
if(strategy.position_size != 0)
53+
strategy.close_all()
54+
strategy.entry("long",strategy.long)
55+
if(short and mom >= 10 and rsi > 50)
56+
if(strategy.position_size != 0)
57+
strategy.close_all()
58+
strategy.entry("short",strategy.short)
59+
60+
if( rsi > 80 or rsi < 20 )
61+
strategy.close_all()
2262

63+
plot(rsi , color = color.blue)
64+
plot(ema10, color=#f37f20)
65+
plot(ema20 , color = color.red)
2366
```
67+
68+
69+
#### 7/19 簡易`EMA`策略
70+
71+
```python
2472
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
2573
// © Crypto-Arsenal
2674

@@ -43,16 +91,132 @@ if (shortCondition)
4391
strategy.close_all()
4492
strategy.entry("My Short Entry Id", strategy.short)
4593
```
46-
47-
- 如何串接任何 `TradingView` 策略: 到 [Strategy](https://crypto-arsenal.io/strategies) > `New Strategy` > `TradingView` ([詳細教學](https://docs.crypto-arsenal.io/docs/tradingview/strategy/sync-by-position))
48-
49-
5094
### `Python`
5195

52-
- 如何回測和實單策略: 到 [Strategy](https://crypto-arsenal.io/strategies) > `New Strategy` > `Technical Indicator` > `EMA`
53-
54-
96+
#### 7/19 Superposition `EMA` Python 策略
97+
98+
```python
99+
"""
100+
Contributed by BCA_Daniel @BCA_Quantrade / Crypto-Arsenal & Alan Wu @Crypto-Arsenal
101+
-
102+
Superposition EMAs are designed to smooth out EMAs and reduce noise interference.
103+
This strategy utilizes four EMAs and uses the output of the previous EMA as the input for the next EMA.
104+
105+
Strategy designer: BCA_Daniel 2023.07.16
106+
"""
107+
class Strategy(StrategyBase):
108+
def __init__(self):
109+
# strategy property
110+
self.subscribed_books = {}
111+
self.period = 60 * 30
112+
self.options = {}
113+
self.last_type = 'sell'
114+
115+
### fast / slow ema period
116+
self.fast_period = 14
117+
self.sp1_period = 14
118+
self.sp2_period =14
119+
self.slow_period = 14
120+
121+
self.divide_quote = 0
122+
self.proportion = 0.2
123+
124+
def on_order_state_change(self, order):
125+
pass
126+
127+
# called every self.period
128+
def trade(self, candles):
129+
exchange, pair, base, quote = CA.get_exchange_pair()
130+
ca_position = self.get_ca_position()
131+
132+
close_price_history = [candle['close'] for candle in candles[exchange][pair]]
133+
high_price_history = [candle['high'] for candle in candles[exchange][pair]]
134+
low_price_history = [candle['low'] for candle in candles[exchange][pair]]
135+
136+
# convert to chronological order for talib
137+
close_price_history.reverse()
138+
high_price_history.reverse()
139+
low_price_history.reverse()
140+
141+
# convert np.array
142+
close_price_history = np.array(close_price_history)
143+
high_price_history = np.array(high_price_history)
144+
low_price_history = np.array(low_price_history)
145+
146+
close_price = close_price_history[0]
147+
high_price = high_price_history[0]
148+
149+
#ema fast / slow create
150+
#np.nan_to_num used to refilled nan to 0 for output array
151+
EMA_fast = talib.EMA(close_price_history, timeperiod=self.fast_period)
152+
EMA_fast_filled = np.nan_to_num(EMA_fast, nan=0)
153+
EMA_superposition_1 = talib.EMA(EMA_fast_filled, timeperiod=self.sp1_period)
154+
EMA_superposition_1_filled = np.nan_to_num(EMA_superposition_1, nan=0)
155+
EMA_superposition_2 = talib.EMA(EMA_superposition_1_filled,self.sp2_period)
156+
EMA_superposition_2_filled = np.nan_to_num(EMA_superposition_2, nan=0)
157+
EMA_slow = talib.EMA(EMA_superposition_2_filled, self.slow_period)
158+
159+
if len(close_price_history) < self.slow_period + 1:
160+
return []
161+
162+
# current ema fast / slow
163+
curr_ema_fast = EMA_fast[-1]
164+
curr_ema_slow = EMA_slow[-1]
165+
166+
# previous time stamp ema
167+
prev_ema_fast = EMA_fast[-2]
168+
prev_ema_slow = EMA_slow[-2]
169+
170+
# get available balance
171+
base_balance = CA.get_balance(exchange, base)
172+
quote_balance = CA.get_balance(exchange, quote)
173+
available_base_amount = base_balance.available
174+
available_quote_amount = quote_balance.available
175+
if self.divide_quote == 0:
176+
self.divide_quote = np.round(available_quote_amount* self.proportion, 5)
177+
178+
# initialize signal to be 0
179+
signal = 0
180+
if available_base_amount< self.divide_quote/high_price and available_base_amount > -self.divide_quote/high_price:
181+
# open long position
182+
if curr_ema_fast > curr_ema_slow and prev_ema_fast < prev_ema_slow:
183+
signal = 1
184+
# open short position
185+
if curr_ema_fast < curr_ema_slow and prev_ema_fast > prev_ema_slow:
186+
signal = -1
187+
188+
# Sell short
189+
if signal == -1:
190+
self['is_shorting'] = 'true'
191+
CA.log('Sell short ' + str(base))
192+
if ca_position:
193+
CA.place_order(exchange, pair, action='close_long', conditional_order_type='OTO', child_conditional_orders=[{'action': 'open_short', 'percent':80}])
194+
else:
195+
CA.place_order(exchange, pair, action='open_short', percent=80)
196+
197+
# Buy long
198+
if signal == 1:
199+
self['is_shorting'] = 'false'
200+
CA.log('Buy ' + str(base))
201+
if ca_position:
202+
CA.place_order(exchange, pair, action='close_short', conditional_order_type='OTO', child_conditional_orders=[{'action': 'open_long', 'percent':80}])
203+
else:
204+
CA.place_order(exchange, pair, action='open_long', percent=80)
205+
206+
207+
# return current total position: -n 0, +n where n is number of contracts
208+
def get_ca_position(self):
209+
exchange, pair, base, quote = CA.get_exchange_pair()
210+
211+
long_position = CA.get_position(exchange, pair, CA.PositionSide.LONG)
212+
if long_position:
213+
return abs(long_position.total_size)
214+
215+
short_position = CA.get_position(exchange, pair, CA.PositionSide.SHORT)
216+
if short_position:
217+
return -1 * abs(short_position.total_size)
218+
219+
return 0
220+
```
55221

56-
![An image from the static](/img/blog/ace791.JPG)
57222

58-
![An image from the static](/img/blog/aceqr.png)

0 commit comments

Comments
 (0)