1
1
---
2
2
slug : bca
3
- title : ACE X CA X Lead Capital 量化課程 7/19
3
+ title : ACE X CA X Lead Capital 量化課程
4
4
author : BCA Daniel
5
5
author_title : Quant Lead & BD & MM
6
6
author_url : https://www.instagram.com/bca_daniel_/
@@ -9,18 +9,66 @@ hide_table_of_contents: false
9
9
tags : [quant, tradingview, python, ema]
10
10
---
11
11
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
+
12
25
### ` Crypto-Arsenal `
13
26
14
27
15
28
- [ 註冊連結] ( 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 `
17
31
18
32
### ` TradingView `
19
33
34
+ #### 7/26 簡易` EMA ` 策略 + 簡易 Filter (濾網) i.e ` RSI ` & ` Momentum `
20
35
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()
22
62
63
+ plot(rsi , color = color.blue)
64
+ plot(ema10, color = # f37f20)
65
+ plot(ema20 , color = color.red)
23
66
```
67
+
68
+
69
+ # ### 7/19 簡易`EMA`策略
70
+
71
+ ```python
24
72
// This source code is subject to the terms of the Mozilla Public License 2.0 at https:// mozilla.org/ MPL / 2.0 /
25
73
// © Crypto- Arsenal
26
74
@@ -43,16 +91,132 @@ if (shortCondition)
43
91
strategy.close_all()
44
92
strategy.entry(" My Short Entry Id" , strategy.short)
45
93
```
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
-
50
94
# ## `Python`
51
95
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
+ ```
55
221
56
- ![ An image from the static] ( /img/blog/ace791.JPG )
57
222
58
- ![ An image from the static] ( /img/blog/aceqr.png )
0 commit comments