Мистер Ран, мой хороший друг, наблюдал за этим показателем в течение долгого времени и рекомендовал мне его до Нового года, чтобы обсудить, можно ли его преобразовать в количественное определение. Жаль, что прокрастинатор так долго не помогал ему исполнить такое желание. На самом деле, мое понимание алгоритмов быстро улучшилось в последнее время. Считается, что однажды я напишу переводчика для языка Пайн. Все может быть питоном. Ну, без лишних ерунд, давайте представим легендарную линию супер тренда.
В новом поколении интеллектуальной торговой системы CMC Markets мы можем выбрать
В основном, это описывает канал, где HL2 (средняя цена k-линии) плюс n раз ATR. Но статья простая, без подробного алгоритма, и я придумал самое удивительное сообщество, TradingView. Действительно, оно действительно есть.
Если посмотреть на график, это соответствует тенденции, но, к сожалению, это всего лишь сигнал тревоги.
Код не слишком длинный, так что давайте попробуем перевести его.!
Полный код сосны - как выше.
Здесь мы создаем новую стратегию на FMZ, назовем ее SuperTrend
Далее, мы установим два параметра, Фактор и Pd
Чтобы лучше упростить работу кода и облегчить понимание, мы должны использовать расширенный пакет расширения данных Python
import pandas as pd
import time
def main():
exchange.SetContractType("quarter")
preTime = 0
Log(exchange.GetAccount())
while True:
records = exchange.GetRecords(PERIOD_M15)
if records and records[-2].Time > preTime:
preTime = records[-2].Time
doTicker(records[:-1])
Sleep(1000 *60)
def doTicker(records):
M15 = pd.DataFrame(records)
M15.columns = ['time','open','high','low','close','volume','OpenInterest']
#HL2
M15['hl2']=(M15['high']+M15['low'])/2
Затем мы ссылаемся на руководство MyLanguage, и алгоритм шагов среднего значения реальной амплитуды флуктуации ATR следующие: TR: MAX ((MAX ((((HIGH-LOW),ABS ((REF ((CLOSE,1) -HIGH)),ABS ((REF ((CLOSE,1) -LOW)); ATR: RMA ((TR,N)
Значение TR - это максимум из следующих трех различий:
При расчете Python
M15['prev_close']=M15['close'].shift(1)
Нам нужно настроить prev_close для получения данных закрыть в предыдущей строке, то есть, переместить закрыть направо одной сетки, чтобы сформировать новый параметр
ranges= [M15['high'] - M15['low'],M15['high']-M15['prev_close'],M15['low']-M15['prev_close']]
Далее мы определяем промежуточную переменную, которая записывает массив из 3 контрастных значений для TR. (HIGH-LOW) (high-prev_close) (low-prev_close)
M15['tr'] = pd.DataFrame(ranges).T.abs().max(axis=1)
Мы определяем новую колонку в наборе данных и называем ее TR. Значение TR - это самое большое абсолютное значение промежуточной переменной, используя функции abs () и max ()
alpha = (1.0 / length) if length > 0 else 0.5
M15['atr']=M15['tr'].ewm(alpha=alpha, min_periods=length).mean()
Наконец, нам нужно вычислить значение ATR, ATR: RMA (TR, N). Оказалось, что алгоритм RMA является фиксированным вариантом алгоритма EMA. N - это переменная, которую мы импортируем.
===
Затем алгоритм ewm используется для расчета ema Полный процесс расчета ATR выглядит следующим образом:
#ATR(PD)
length=Pd
M15['prev_close']=M15['close'].shift(1)
ranges= [M15['high'] - M15['low'],M15['high']-M15['prev_close'],M15['low']-M15['prev_close']]
M15['tr'] = pd.DataFrame(ranges).T.abs().max(axis=1)
alpha = (1.0 / length) if length > 0 else 0.5
M15['atr']=M15['tr'].ewm(alpha=alpha, min_periods=length).mean()
9 Начните вычислять Up и Dn
M15['Up']=M15['hl2']-(Factor*M15['atr'])
M15['Dn']=M15['hl2']+(Factor*M15['atr'])
Up=hl2 - ((Фактор * atr) Dn=hl2 +(Фактор * atr) Разве это не просто?
Вот основная часть кода из строк 15-21 из ТВ
TrendUp=close[1]>TrendUp[1]? max(Up,TrendUp[1]) : Up
TrendDown=close[1]<TrendDown[1]? min(Dn,TrendDown[1]) : Dn
Trend = close > TrendDown[1] ? 1: close< TrendUp[1]? -1: nz(Trend[1],1)
Tsl = Trend==1? TrendUp: TrendDown
linecolor = Trend == 1 ? green : red
Основным пунктом данного пункта является выражение того, что Если он находится в бычьей стадии, (нижняя линия) TrendUp=max (Up, TrendUp [1]) Если он находится в стадии падения, (верхняя линия) TrendDown=min (Dn, TrendDown [1]) То есть, в тренде, значение ATR использует технологию, аналогичную стратегии Бандита Боллинджера. Продолжайте сужать другую сторону канала.
Здесь каждый расчет TrendUp и TrendDown требует самоитерации. То есть каждый шаг должен быть рассчитан в соответствии с предыдущим шагом. Следовательно, набор данных должен быть итерационным в цикле.
Сначала мы создаем новые поля TrendUp, TrendDown, Trend, linecolor для набора данных. Затем мы используем грамматический fillna (0) для заполнения данных с нулевым значением в ранее рассчитанном результате с 0
M15['TrendUp']=0.0
M15['TrendDown']=0.0
M15['Trend']=1
M15['Tsl']=0.0
M15['linecolor']='Homily'
M15 = M15.fillna(0)
Включить цикл " for " Использование тройной операции Python в петле
for x in range(len(M15)):
Вычислить TrendUp TrendUp = MAX(Up,TrendUp[-1]) если близко[-1]>TrendUp[-1] в противном случае Up Это приблизительно означает, что если предыдущее закрытие>предыдущее TrendUp верно, то будет принято максимальное значение между Up и предыдущим TrendUp; если нет, то значение Up будет принято и передано текущему TrendUp.
M15['TrendUp'].values[x] = max(M15['Up'].values[x],M15['TrendUp'].values[x-1]) if (M15['close'].values[x-1]>M15['TrendUp'].values[x-1]) else M15['Up'].values[x]
Аналогичным образом, вычислить TrendDown TrendDown=min(Dn,TrendDown[-1]) если близко[-1]
M15['TrendDown'].values[x] = min(M15['Dn'].values[x],M15['TrendDown'].values[x-1]) if (M15['close'].values[x-1]<M15['TrendDown'].values[x-1]) else M15['Dn'].values[x]
Следующий флаг для расчета направления управления. Trend= 1 если (закрыть > TrendDown[-1]) иначе (x) x = -1 если (close< TrendUp[-1]) в противном случае Trend[-1]
Это означает, что если цена закрытия>предыдущий TrendDown, возьмите значение 1 (бычий). Если цена закрытия ниже предыдущего TrendUp, возьмите значение -1 (медвежьей). Если нет, возьмите предыдущий Trend (что означает неизменный) Если перевести на язык образа, то это прорыв верхнего флага переходного пути для бычьего; и прорыв нижнего флага переходного пути для медвежьего.
M15['Tsl'].values[x] = M15['TrendUp'].values[x] if (M15['Trend'].values[x]==1) else M15['TrendDown'].values[x]
Вычислить Tsl и Linecolor
Tsl=RendUp если (Trend==1) иное TrendDown
Tsl - это значение, используемое для представления SuperTrend на изображении. Это означает, что мы отмечаем снижающийся трек на изображении, когда мы находимся в бычьем, и отмечаем верхний трек на изображении, когда мы находимся в медленном.
linecolor=
M15['Tsl'].values[x] = M15['TrendUp'].values[x] if (M15['Trend'].values[x]==1) else M15['TrendDown'].values[x]
M15['linecolor'].values[x]= 'green' if ( M15['Trend'].values[x]==1) else 'red'
Следующие 23-30 строк кода - это в основном чертежи сюжетов, которые здесь не объясняются.
Наконец, есть 2 строки кода для управления сигналом покупки и продажи В Tradeview, это означает, что сигнал дается после обратного флага Конвертируйте условный комментарий в Python. Если последний флаг тренда меняется с -1 на 1, это означает, что верхнее сопротивление превышено и открыта длинная позиция. Если последний флаг тренда меняется с 1 на -1, это означает, что поддержка вниз превышена и открыта короткая позиция.
if(M15['Trend'].values[-1] == 1 and M15['Trend'].values[-2] == -1):
Log('SuperTrend V.1 Alert Long',"Create Order Buy)
if(M15['Trend'].values[-1] == -1 and M15['Trend'].values[-2] == 1):
Log('SuperTrend V.1 Alert Long',"Create Order Sell)
Полный код:
M15['TrendUp']=0.0
M15['TrendDown']=0.0
M15['Trend']=1
M15['Tsl']=0.0
M15['linecolor']='Homily'
M15 = M15.fillna(0)
for x in range(len(M15)):
M15['TrendUp'].values[x] = max(M15['Up'].values[x],M15['TrendUp'].values[x-1]) if (M15['close'].values[x-1]>M15['TrendUp'].values[x-1]) else M15['Up'].values[x]
M15['TrendDown'].values[x] = min(M15['Dn'].values[x],M15['TrendDown'].values[x-1]) if (M15['close'].values[x-1]<M15['TrendDown'].values[x-1]) else M15['Dn'].values[x]
M15['Trend'].values[x] = 1 if (M15['close'].values[x] > M15['TrendDown'].values[x-1]) else ( -1 if (M15['close'].values[x]< M15['TrendUp'].values[x-1])else M15['Trend'].values[x-1] )
M15['Tsl'].values[x] = M15['TrendUp'].values[x] if (M15['Trend'].values[x]==1) else M15['TrendDown'].values[x]
M15['linecolor'].values[x]= 'green' if ( M15['Trend'].values[x]==1) else 'red'
if(M15['Trend'].values[-1] == 1 and M15['Trend'].values[-2] == -1):
Log('SuperTrend V.1 Alert Long',"Create Order Buy)
Log('Tsl=',Tsl)
if(M15['Trend'].values[-1] == -1 and M15['Trend'].values[-2] == 1):
Log('SuperTrend V.1 Alert Long',"Create Order Sell)
Log('Tsl=',Tsl)
Я скорректировал структуру кода. И я объединил инструкции, связанные с покупкой и продажей в стратегию. Вот полный код:
'''backtest
start: 2019-05-01 00:00:00
end: 2020-04-21 00:00:00
period: 15m
exchanges: [{"eid":"Futures_OKCoin","currency":"BTC_USD"}]
'''
import pandas as pd
import time
def main():
exchange.SetContractType("quarter")
preTime = 0
Log(exchange.GetAccount())
while True:
records = exchange.GetRecords(PERIOD_M15)
if records and records[-2].Time > preTime:
preTime = records[-2].Time
doTicker(records[:-1])
Sleep(1000 *60)
def doTicker(records):
#Log('onTick',exchange.GetTicker())
M15 = pd.DataFrame(records)
#Factor=3
#Pd=7
M15.columns = ['time','open','high','low','close','volume','OpenInterest']
#HL2
M15['hl2']=(M15['high']+M15['low'])/2
#ATR(PD)
length=Pd
M15['prev_close']=M15['close'].shift(1)
ranges= [M15['high'] - M15['low'],M15['high']-M15['prev_close'],M15['low']-M15['prev_close']]
M15['tr'] = pd.DataFrame(ranges).T.abs().max(axis=1)
alpha = (1.0 / length) if length > 0 else 0.5
M15['atr']=M15['tr'].ewm(alpha=alpha, min_periods=length).mean()
M15['Up']=M15['hl2']-(Factor*M15['atr'])
M15['Dn']=M15['hl2']+(Factor*M15['atr'])
M15['TrendUp']=0.0
M15['TrendDown']=0.0
M15['Trend']=1
M15['Tsl']=0.0
M15['linecolor']='Homily'
M15 = M15.fillna(0)
for x in range(len(M15)):
M15['TrendUp'].values[x] = max(M15['Up'].values[x],M15['TrendUp'].values[x-1]) if (M15['close'].values[x-1]>M15['TrendUp'].values[x-1]) else M15['Up'].values[x]
M15['TrendDown'].values[x] = min(M15['Dn'].values[x],M15['TrendDown'].values[x-1]) if (M15['close'].values[x-1]<M15['TrendDown'].values[x-1]) else M15['Dn'].values[x]
M15['Trend'].values[x] = 1 if (M15['close'].values[x] > M15['TrendDown'].values[x-1]) else ( -1 if (M15['close'].values[x]< M15['TrendUp'].values[x-1])else M15['Trend'].values[x-1] )
M15['Tsl'].values[x] = M15['TrendUp'].values[x] if (M15['Trend'].values[x]==1) else M15['TrendDown'].values[x]
M15['linecolor'].values[x]= 'Long' if ( M15['Trend'].values[x]==1) else 'Short'
linecolor=M15['linecolor'].values[-2]
close=M15['close'].values[-2]
Tsl=M15['Tsl'].values[-2]
if(M15['Trend'].values[-1] == 1 and M15['Trend'].values[-2] == -1):
Log('SuperTrend V.1 Alert Long','Create Order Buy')
Log('Tsl=',Tsl)
position = exchange.GetPosition()
if len(position) > 0:
Amount=position[0]["Amount"]
exchange.SetDirection("closesell")
exchange.Buy(_C(exchange.GetTicker).Sell*1.01, Amount);
exchange.SetDirection("buy")
exchange.Buy(_C(exchange.GetTicker).Sell*1.01, vol);
if(M15['Trend'].values[-1] == -1 and M15['Trend'].values[-2] == 1):
Log('SuperTrend V.1 Alert Long','Create Order Sell')
Log('Tsl=',Tsl)
position = exchange.GetPosition()
if len(position) > 0:
Amount=position[0]["Amount"]
exchange.SetDirection("closebuy")
exchange.Sell(_C(exchange.GetTicker).Buy*0.99,Amount);
exchange.SetDirection("sell")
exchange.Sell(_C(exchange.GetTicker).Buy*0.99, vol*2);
Адрес общественной стратегии:https://www.fmz.com/strategy/200625
Мы выбрали данные прошлого года для обратного тестирования. Мы используем квартальный контракт OKEX на 15 минут. Установленные параметры: Фактор = 3 Pd=45 Vol=100 (100 контрактов на каждый заказ) Годовая доходность составляет около 33%. Вообще-то, вывод не очень большой, Резкое сокращение 312 имело относительно большое влияние на систему, Если нет 312, то доходы должны быть лучше.
SuperTrend - очень хорошая торговая система.
Основной принцип системы SuperTrend заключается в принятии стратегии прорыва канала ATR (аналогичной каналу Кента) Однако его изменение обусловлено в основном использованием стратегии сужения Бандита Боллинджера, или обратного принципа Донкиана. При рыночной операции верхние и нижние каналы постоянно сужаются. Для достижения работы рулевого прорыва канала. (После прорыва канала верхние и нижние рельсы вернутся к исходному значению)
Я выставляю, dn, TrendUp и TrendDn отдельно на TradeView, что облегчает понимание стратегии. Посмотрите на это на первый взгляд:
Кроме того, есть версия js на github. Я не очень хорош в js, но, похоже, что что-то не так с if-указанием. Адрес:https://github.com/Dodo33/gekko-supertrend-strategy/blob/master/Supertrend.js
Наконец-то я нашла оригинальную версию. Опубликовано 29 мая 2013 Автор - Раджандран Р. Код C++ был опубликован на форуме Mt4:https://www.mql5.com/en/code/viewcode/10851/128437/Non_Repainting_SuperTrend.mq4Я примерно понял смысл C++, и перепишу его, когда будет возможность.
Надеюсь, вы сможете извлечь из него суть. Это сложно!