Ограничение количества позиций в Quantstrat

Последние несколько дней я ломал голову, пытаясь понять, как ограничить количество позиций в стратегии. Это стратегия прорыва канала (вход в длинную позицию/закрытие 20-дневного канала прорыва с 10-дневным максимумом/минимумом стоп-лосса).

Я не хочу, чтобы система превратилась в пирамиду. Принимается только 1 позиция, т.е. если в первый день у меня есть сигнал, а рынок продолжает тренд, он будет печатать новые сигналы, но их нужно отклонить, так как мы уже в позиции.

Я пробовал все, что нашел, но ничего не смог добиться. Я знаю, что мне нужно настроить osMaxPos и ​​addPosLimit, но, похоже, я делаю это неправильно.

Вот мой код. Заранее спасибо.

#Import des données
GBPUSD <- getdata("GBPUSD.csv")
GBPUSD <- getdata("GBPUSD.csv")
AUDUSD <- getdata("AUDUSD.csv")
EURUSD <- getdata("EURUSD.csv")
XAUUSD <- getdata("XAUUSD.csv")
EURCHF <- getdata("EURCHF.csv")

### Création des devises
currency(c("USD","EUR","AUD","GBP","XAU","CHF"))
exchange_rate(c("EURUSD","GBPUSD","AUDUSD","XAUUSD","EURCHF"),"USD")
symbols <- c("GBPUSD","AUDUSD","EURUSD")
tradesize <- 1000000



init.date <- "2001-09-04"    #date d'initialisation de l'environement
start.date <- "2001-10-01"       #1ere date du jeu de donnée
end.date <- Sys.Date()       #dernière date du jeu de donnée
initial.capital <- 1000000      #Capital de départ
Breakout <- strategy("Breakout")


portfolio.st <- account.st <- strat.st <- "Breakout"

if (!exists('.blotter')) .blotter <- new.env()
if (!exists('.strategy')) .strategy <- new.env()

initPortf(portfolio.st,        #nom du book
          symbols = symbols,  #list des instruments
          initDate=init.date,  #date de départ du book
          currency='USD')     #devise de référence du book

initAcct(account.st,                 #nom du compte
         portfolios = portfolio.st,  #nom du portfeuille rattaché au compte
         initDate = init.date,       #date de départ du compte
         currency = "USD",           #devise du compte
         initEq = initial.capital)   #capital de départ du compte

initOrders(portfolio.st,            #initialisation du container des orgers
           initDate = init.date)    #date de départ du book d'ordre

strategy("Breakout",store = TRUE)


#Definition des indicateurs
add.indicator("Breakout",
              name = "DonchianChannel",
              arguments=list(HL=quote(cbind(Hi(mktdata)[,1],Lo(mktdata)[,1])), n=20,include.lag=TRUE), label="Donchian20")

add.indicator("Breakout",
              name = "DonchianChannel",
              arguments=list(HL=quote(cbind(Hi(mktdata)[,1],Lo(mktdata)[,1])), n=10,include.lag=TRUE), label="Donchian10")


##Definition des signaux

add.signal("Breakout",                #nom de la strategie
           name="sigCrossover",      #type de signal
           arguments = list(columns =c("Close","high.Donchian20"), #liste des colonnes pour déterminer le signal
                            relationship="gt"),   #type de relation du signal (sup ou égal, sup, inférieur etc..)
           label = "long")        #label de la colonne du signal

add.signal("Breakout",                #nom de la strategie
           name="sigCrossover",      #type de signal
           arguments = list(columns =c("Close","low.Donchian10"), #liste des colonnes pour déterminer le signal
                            relationship="lt"),   #type de relation du signal (sup ou égal, sup, inférieur etc..)
           label = "exitlong")        #label de la colonne du signal


add.signal("Breakout",                #nom de la strategie
           name="sigCrossover",      #type de signal
           arguments = list(columns =c("Close","low.Donchian20"), #liste des colonnes pour déterminer le signal
                            relationship="lt"),   #type de relation du signal (sup ou égal, sup, inférieur etc..)
           label = "short")   

add.signal("Breakout",                #nom de la strategie
           name="sigCrossover",      #type de signal
           arguments = list(columns =c("Close","high.Donchian10"), #liste des colonnes pour déterminer le signal
                            relationship="gt"),   #type de relation du signal (sup ou égal, sup, inférieur etc..)
           label = "exitshort")        #label de la colonne du signal


#Limite

#addPosLimit( portfolio = "Breakout", # add position limit rules
#             symbol = "AUDUSD",
#            timestamp = init.date,
#            maxpos = tradesize)

addPosLimit("Breakout","AUDUSD",maxpos = 1, minpos = -1,timestamp =  as.POSIXct(init.date))
getPosLimit(portfolio = "Breakout","AUDUSD", timestamp = as.POSIXct(init.date))

##Definition des règles

add.rule("Breakout",                               #nom de la strategie 
         name = "ruleSignal",                      #
         arguments = list(sigcol ="long",          #nom de la colonne à vérifier
                          sigval = TRUE,           #Application de la règle si signal
                          orderqty=tradesize,        #taille de l'ordre
                          osFun = osMaxPos,
                          replace = FALSE,
                          ordertype = "market",    #type d'ordre
                          orderside ="long"),   #sens
         type = "enter",          #ouverture ou fermeture de pose
         label = "Enterlong")    #label si exécution

add.rule("Breakout",                                  #nom de la strategie 
         name = "ruleSignal",                      #
         arguments = list(sigcol ="exitlong",          #nom de la colonne à vérifier
                          sigval = TRUE,           #Application de la règle si signal
                          orderqty="all",        #taille de l'ordre
                          replace = FALSE,
                          ordertype = "market",    #type d'ordre
                          orderside ="long"),   #sens
         type = "exit",          #ouverture ou fermeture de pose
         label = "Exitlong")    #label si exécution


add.rule("Breakout",                                  #nom de la strategie 
         name = "ruleSignal",                      #
         arguments = list(sigcol ="short",          #nom de la colonne à vérifier
                          sigval = TRUE,           #Application de la règle si signal
                          orderqty=-tradesize,#taille de l'ordre
                          replace = FALSE,
                          ordertype = "market",    #type d'ordre
                          orderside ="short"),   #sens
         type = "enter",          #ouverture ou fermeture de pose
         label = "Entershort")    #label si exécution

add.rule("Breakout",                                  #nom de la strategie 
         name = "ruleSignal",                      #
         arguments = list(sigcol ="exitshort",          #nom de la colonne à vérifier
                          sigval = TRUE,           #Application de la règle si signal
                          orderqty="all",#taille de l'ordre
                          osFun = osMaxPos,
                          replace = FALSE,
                          ordertype = "market",    #type d'ordre
                          orderside ="short"),   #sens
         type = "exit",          #ouverture ou fermeture de pose
         label = "Exitshort")    #label si exécution






out <- applyStrategy("Breakout", portfolios = portfolio.st)

person NicolasB    schedule 20.01.2017    source источник
comment
Вам нужно указать, какой пакет содержит функцию getdata. Вам также необходимо предоставить некоторые данные (мы не можем получить доступ к файлам CSV на вашем компьютере).   -  person Joshua Ulrich    schedule 20.01.2017


Ответы (1)


Есть довольно много проблем с вашим кодом. Я постараюсь объяснить их все.

Инициализация

Обычно вам не нужно устанавливать initDate в вызовах initPortf, initAcct и initOrders. Неправильная установка этого значения может вызвать проблемы. Таким образом, эти вызовы должны быть:

initPortf(portfolio.st,       #nom du book
          symbols = symbols,  #list des instruments
          currency='USD')     #devise de référence du book

initAcct(account.st,                 #nom du compte
         portfolios = portfolio.st,  #nom du portfeuille rattaché au compte
         currency = "USD",           #devise du compte
         initEq = initial.capital)   #capital de départ du compte

initOrders(portfolio.st)             #initialisation du container des orgers

Ограничения позиций

Вы устанавливаете максимальный/минимальный размер сделки равным 1 в своем вызове addPosLimit, но ваш размер сделки равен 1 миллиону. Таким образом, любой ордер будет отклонен, потому что он превысит лимит вашей позиции. Вы также должны знать, что аргумент timestamp для addPosLimit определяет, когда ограничения вступают в силу. Если вы хотите, чтобы они всегда действовали, вы должны установить метку времени на время до первого наблюдения в ваших данных. Также обратите внимание, что вы установили лимиты позиций только для AUDUSD. Вам необходимо создать лимиты позиций для каждого символа.

addPosLimit("Breakout", "GBPUSD", maxpos = tradesize, timestamp = start(GBPUSD)-1)
addPosLimit("Breakout", "AUDUSD", maxpos = tradesize, timestamp = start(AUDUSD)-1)
addPosLimit("Breakout", "EURUSD", maxpos = tradesize, timestamp = start(EURUSD)-1)

Правила

Одна проблема заключается в том, что вы передали osFun в ruleSignal. ruleSignal не имеет аргумента osFun. Аргумент osFUN (регистр имеет значение). Другая проблема заключается в том, что вы указали osFun = osMaxPos в коротком правиле выхода, а не в правиле входа.

add.rule("Breakout", name = "ruleSignal",
         arguments = list(sigcol = "long",      #nom de la colonne à vérifier
                          sigval = TRUE,        #Application de la règle si signal
                          orderqty = tradesize, #taille de l'ordre
                          osFUN = osMaxPos,
                          replace = FALSE,
                          ordertype = "market", #type d'ordre
                          orderside = "long"),  #sens
         type = "enter", label = "Enterlong")

add.rule("Breakout", name = "ruleSignal",
         arguments = list(sigcol = "exitlong",  #nom de la colonne à vérifier
                          sigval = TRUE,        #Application de la règle si signal
                          orderqty = "all",     #taille de l'ordre
                          replace = FALSE,
                          ordertype = "market", #type d'ordre
                          orderside = "long"),  #sens
         type = "exit", label = "Exitlong")

add.rule("Breakout", name = "ruleSignal",
         arguments = list(sigcol = "short",     #nom de la colonne à vérifier
                          sigval = TRUE,        #Application de la règle si signal
                          orderqty = -tradesize,#taille de l'ordre
                          osFUN = osMaxPos,
                          replace = FALSE,
                          ordertype = "market",  #type d'ordre
                          orderside = "short"),  #sens
         type = "enter", label = "Entershort")

add.rule("Breakout", name = "ruleSignal",
         arguments = list(sigcol = "exitshort",  #nom de la colonne à vérifier
                          sigval = TRUE,         #Application de la règle si signal
                          orderqty = "all",      #taille de l'ordre
                          replace = FALSE,
                          ordertype = "market",  #type d'ordre
                          orderside = "short"),  #sens
         type = "exit", label = "Exitshort")
person Joshua Ulrich    schedule 20.01.2017
comment
Вы фантастика. Спасибо, что нашли время проанализировать мой плохой код. - person NicolasB; 20.01.2017
comment
@NicolasB Вам следует подумать о том, чтобы принять этот очень подробный ответ. - person FXQuantTrader; 06.02.2017
comment
что вы имеете в виду @FXQuantTrader? - person NicolasB; 08.02.2017
comment
comment
Я принял ответ. Еще раз, я очень ценю вашу помощь, Джошуа :) - person NicolasB; 09.02.2017
comment
Я пробовал это с фьючерсной стратегией, где моя максимальная позиция составляет 1/-1. Это означает, что если я торгую на развороте, я ожидаю размер ордера 2 (для перехода из позиции -1 в позицию 1 или наоборот). Тем не менее, в моей книге заказов ни один заказ не превышает размер 1. Можете ли вы помочь мне понять, что я делаю неправильно? - person dannytoone; 01.11.2018