Количественные стратегии, основанные на скорости изменения


Дата создания: 2023-12-12 15:56:56 Последнее изменение: 2023-12-12 15:56:56
Копировать: 0 Количество просмотров: 655
1
Подписаться
1621
Подписчики

Количественные стратегии, основанные на скорости изменения

Обзор

Эта стратегия основана на изменении показателя (ROC) для определения движения рынка и получения торговых сигналов. Основная идея стратегии заключается в том, чтобы следовать долгосрочным тенденциям и получать доходы, превышающие рынок, принимая большие риски.

Стратегический принцип

Правила участия

  • Если ROC>0, то сделайте больше; если ROC, то сделайте пусто. Используйте положительное и отрицательное значения показателя ROC, чтобы определить направление движения.
  • Для того, чтобы отфильтровать колебания, сигналы о сделках будут подаваться только в том случае, если ROC будет находиться на одной стороне в течение двух дней подряд.

Стоп-лосс правила

Устанавливается 6% стоп-пароль. Когда запускается стоп-пароль, изменяется направление позиции. Это означает, что мы, возможно, находимся на неправильной стороне рынка и требуем своевременной обратной операции.

Противопузырной механизм

Если ROC превышает 200, то считается, что это пузырь. Когда ROC опускается ниже пузыря, то создается сигнал о пустоте. При этом требуется, чтобы пузырь продолжался не менее 1 недели.

Управление деньгами

Использование фиксированной позиции + метода наращивания. За каждый рост или падение 400 долларов, увеличение или уменьшение позиции в размере 200 долларов. Таким образом, можно использовать прибыль для набора запасов, чтобы получить большую прибыль, но также увеличить отзыв.

Анализ преимуществ

Это стратегия, которая отслеживает долгосрочные тенденции.

  1. В этом случае, если вы используете стратегию “Тренд-трейдинга”, вы можете легко получить долгосрочную положительную прибыль.
  2. Использование стоп-лосса для управления риском может снизить влияние краткосрочных колебаний.
  3. Противопузырьковые механизмы позволяют избежать повышения цен на рынке.
  4. Фиксированные позиции и растущее управление капиталом позволяют ему получать индексированный рост в условиях роста.

Анализ рисков

Однако эта стратегия также несет в себе некоторые риски:

  1. ROC-показатели подвержены воздействию колебаний, что приводит к ошибочным сигналам. Можно рассмотреть возможность комбинированной фильтрации с другими показателями.
  2. При использовании, без учета стоимости сделки, прибыль будет ниже, чем при оценке.
  3. Неправильно настроенные параметры защиты от пузырьков также могут быть пропущены.
  4. Фиксированные позиции плюс наращивание увеличивают убытки при их выводе.

Направление оптимизации

Эта стратегия может быть оптимизирована в следующих аспектах:

  1. Добавление других показателей, составляющих торговую систему, чтобы отфильтровать ошибочные сигналы. Например, добавление средней линии, показателей, таких как волатильность.
  2. Оптимизация параметров защиты от пузырьков, установка более точного механизма распознавания пузырьков.
  3. Настройка фиксированных позиций и нарастающих параметров для достижения лучшего баланса риска и прибыли.
  4. Добавление механизма автоматического остановки убытков.
  5. Учитывая влияние сделок на стоимость, устанавливаются более реалистичные критерии входа.

Подвести итог

В целом, это долгосрочная стратегия отслеживания, основанная на показателях ROC. Это активная стратегия, которая позволяет получать дополнительные доходы, превышающие основную массу, принимая большие риски. Нам нужно правильно оптимизировать ее, чтобы она могла использоваться на практике.

Исходный код стратегии
/*backtest
start: 2022-12-05 00:00:00
end: 2023-12-11 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © gsanson66


//This strategy use the Rate of Change (ROC) of the closing price to send enter signal. 
//@version=5
strategy("RATE OF CHANGE BACKTESTING", shorttitle="ROC BACKTESTING", overlay=false, precision=3, initial_capital=1000, default_qty_type=strategy.cash, default_qty_value=950, commission_type=strategy.commission.percent, commission_value=0.18)


//--------------------------------FUNCTIONS-----------------------------------//

//@function Displays text passed to `txt` when called.
debugLabel(txt, color, loc) =>
    label.new(bar_index, loc, text = txt, color=color, style = label.style_label_lower_right, textcolor = color.black, size = size.small)

//@function which looks if the close date of the current bar falls inside the date range
inBacktestPeriod(start, end) => (time >= start) and (time <= end)


//----------------------------------USER INPUTS----------------------------------//

//Technical parameters
rocLength = input.int(defval=365, minval=0, title='ROC Length', group="Technical parameters")
bubbleValue = input.int(defval=200, minval=0, title="ROC Bubble signal", group="Technical parameters")
//Risk management
stopLossInput = input.float(defval=10, minval=0, title="Stop Loss (in %)", group="Risk Management")
//Money management
fixedRatio = input.int(defval=400, minval=1, title="Fixed Ratio Value ($)", group="Money Management")
increasingOrderAmount = input.int(defval=200, minval=1, title="Increasing Order Amount ($)", group="Money Management")
//Backtesting period
startDate = input(title="Start Date", defval=timestamp("1 Jan 2017 00:00:00"), group="Backtesting Period")
endDate = input(title="End Date", defval=timestamp("1 July 2024 00:00:00"), group="Backtesting Period")


//-------------------------------------VARIABLES INITIALISATION-----------------------------//

roc = (close/close[rocLength] - 1)*100
midlineConst = 0
var bool inBubble = na
bool shortBubbleCondition = na
equity = strategy.equity - strategy.openprofit
strategy.initial_capital = 50000
var float capital_ref = strategy.initial_capital
var float cashOrder = strategy.initial_capital * 0.95
bool inRange = na


//------------------------------CHECKING SOME CONDITIONS ON EACH SCRIPT EXECUTION-------------------------------//

//Checking if the date belong to the range
inRange := true

//Checking if we are in a bubble
if roc > bubbleValue and not inBubble
    inBubble := true

//Checking if the bubble is over
if roc < 0 and inBubble
    inBubble := false

//Checking the condition to short the bubble : The ROC must be above the bubblevalue for at least 1 week
if roc[1]>bubbleValue and roc[2]>bubbleValue and roc[3]>bubbleValue and roc[4]>bubbleValue and roc[5]>bubbleValue and roc[6]>bubbleValue and roc[7]>bubbleValue
    shortBubbleCondition := true

//Checking performances of the strategy
if equity > capital_ref + fixedRatio
    spread = (equity - capital_ref)/fixedRatio
    nb_level = int(spread)
    increasingOrder = nb_level * increasingOrderAmount
    cashOrder := cashOrder + increasingOrder
    capital_ref := capital_ref + nb_level*fixedRatio
if equity < capital_ref - fixedRatio
    spread = (capital_ref - equity)/fixedRatio
    nb_level = int(spread)
    decreasingOrder = nb_level * increasingOrderAmount
    cashOrder := cashOrder - decreasingOrder
    capital_ref := capital_ref - nb_level*fixedRatio

//Checking if we close all trades in case where we exit the backtesting period
if strategy.position_size!=0 and not inRange
    debugLabel("END OF BACKTESTING PERIOD : we close the trade", color=color.rgb(116, 116, 116), loc=roc)
    strategy.close_all()


//-------------------------------LONG/SHORT CONDITION-------------------------------//

//Long condition
//We reduce noise by taking signal only if the last roc value is in the same side as the current one
if (strategy.position_size<=0 and ta.crossover(roc, midlineConst)[1] and roc>0 and inRange)
    //If we were in a short position, we pass to a long position
    qty = cashOrder/close
    strategy.entry("Long", strategy.long, qty)
    stopLoss = close * (1-stopLossInput/100)
    strategy.exit("Long Risk Managment", "Long", stop=stopLoss)

//Short condition
//We take a short position if we are in a bubble and roc is decreasing
if (strategy.position_size>=0 and ta.crossunder(roc, midlineConst)[1] and roc<0 and inRange) or 
     (strategy.position_size>=0 and inBubble and ta.crossunder(roc, bubbleValue) and shortBubbleCondition and inRange)
    //If we were in a long position, we pass to a short position
    qty = cashOrder/close
    strategy.entry("Short", strategy.short, qty)
    stopLoss = close * (1+stopLossInput/100)
    strategy.exit("Short Risk Managment", "Short", stop=stopLoss)


//--------------------------------RISK MANAGEMENT--------------------------------------//

//We manage our risk and change the sense of position after SL is hitten
if strategy.position_size == 0 and inRange
    //We find the direction of the last trade
    id = strategy.closedtrades.entry_id(strategy.closedtrades-1)
    if id == "Short"
        qty = cashOrder/close
        strategy.entry("Long", strategy.long, qty)
        stopLoss = close * (1-stopLossInput/100)
        strategy.exit("Long Risk Managment", "Long", stop=stopLoss)
    else if id =="Long"
        qty = cashOrder/close
        strategy.entry("Short", strategy.short, qty)
        stopLoss = close * (1+stopLossInput/100)
        strategy.exit("Short Risk Managment", "Short", stop=stopLoss)


//---------------------------------PLOTTING ELEMENTS---------------------------------------//

//Plotting of ROC
rocPlot = plot(roc, "ROC", color=#7E57C2)
midline = hline(0, "ROC Middle Band", color=color.new(#787B86, 25))
midLinePlot = plot(0, color = na, editable = false, display = display.none)
fill(rocPlot, midLinePlot, 40, 0, top_color = strategy.position_size>0 ? color.new(color.green, 0) : strategy.position_size<0 ? color.new(color.red, 0) : na, bottom_color = strategy.position_size>0 ? color.new(color.green, 100) : strategy.position_size<0 ? color.new(color.red, 100) : na,  title = "Positive area")
fill(rocPlot, midLinePlot, 0,  -40,  top_color = strategy.position_size<0 ? color.new(color.red, 100) : strategy.position_size>0 ? color.new(color.green, 100) : na, bottom_color = strategy.position_size<0 ? color.new(color.red, 0) : strategy.position_size>0 ? color.new(color.green, 0) : na, title = "Negative area")