Monday 26 August 2019

Ddply moving average


Blog de Vincent Zoonekynds Muitos problemas nas estatísticas ou na aprendizagem por máquina são da forma que encontram os valores dos parâmetros que minimizam alguma medida de erro. Mas, em alguns casos, também são impostas restrições aos parâmetros: por exemplo, que eles devem somar até 1, ou que no máximo 10 deles não sejam zero - isso adiciona uma camada combinatória ao problema, o que o torna Muito mais difícil de resolver. Nesta nota, vou dar um guia para (alguns) dos pacotes de otimização em R e explicar (alguns dos) algoritmos por trás deles. Os solucionadores acessíveis a partir de R têm algumas limitações, como a incapacidade de lidar com restrições binárias ou integrais (em problemas não lineares): veremos como resolver esses problemas. Quando você começa a usar o software de otimização, você luta para estimular o problema na forma esperada pelo software (muitas vezes você precisa reformulá-lo para torná-lo linear ou quadrático e, em seguida, escrevê-lo em forma de matriz). Isso não é muito fácil de usar. Veremos que é possível especificar problemas de otimização de forma perfeitamente legível. Muitos dos exemplos serão retirados da otimização de finanças e portfólio. Introdução Otimização refere-se ao problema de encontrar o mínimo ou o máximo de alguma função, sujeito a algumas restrições. Problemas de otimização (às vezes chamados de programas de otimização - a palavra vem de uma era sem computadores e sem programas de computador) são muitas vezes escritas como onde x é um vetor e f, g, h funções arbitrárias. Vamos primeiro descrever algumas das complicações que podem ocorrer quando você enfrenta um problema de otimização. Local extrema Uma vez que muitos algoritmos de otimização usam apenas informações locais, eles podem ficar presos em um extremum local. No exemplo a seguir, existem muitos vales: o computador encontrará um deles, mas não necessariamente o mais baixo. (Neste exemplo, você poderia usar um algoritmo de otimização mais robusto, como o DEoptim, ou, melhor, livrar-se das ondas e extrema local, expandindo o seno.) Reparação para remover restrições A situação é muitas vezes complicada pela presença De restrições. Felizmente, muitas vezes podem ser removidas reformulando o problema: se você tiver uma restrição de igualdade, muitas vezes pode expressar uma das incógnitas como uma função dos outros se você tiver uma restrição de desigualdade do formulário x0, você pode substituir x por exp. (Y) ou y2 ou log (1exp (y)), onde y é um novo desconhecido. Por exemplo, consideremos uma regressão restrita: o problema pode ser reparametrizado da seguinte maneira. Infelizmente, essa abordagem nem sempre funciona. Considere o seguinte problema. Dado n números a1. Um, queremos encontrar x1. Xn, o mais próximo possível do ai, mas em ordem crescente. Se usarmos a soma das distâncias quadradas para medir a proximidade, o problema de otimização pode ser escrito como Em vez de procurar x1, x2. Xn, podemos procurar O problema se torna A restrição é mais simples, mas não nos conseguimos completamente livrar. Mas podemos escrever y exp (z): isso irá garantir que ele permaneça positivo. As restrições desapareceram completamente: temos uma solução muito ruim. Um dos problemas é que a solução está na fronteira, mas a fronteira não é mais alcançável depois da nossa reparametrização. Neste caso, a programação quadrática é uma abordagem melhor. Penas duras e suaves Em alguns casos, as restrições são muito irregulares ou muito numerosas: não podemos removê-las. Em vez disso, podemos adicionar uma penalidade por violações de restrições e aumentar progressivamente a penalidade. Otimização em R As funções para resolver problemas de otimização estão dispersas em muitos pacotes, cada um limitado a (ou otimizado para) problemas de um determinado tipo. Para complicar as coisas, as interfaces são diferentes. Aqui estão alguns deles. Houve algumas tentativas para unificar todos esses pacotes, p. ex. Os pacotes ROI e optimx (eles permitem que você primeiro descreva o problema de otimização, sempre da mesma maneira, independentemente do tipo de problemm e somente então para selecionar o solucionador a ser usado, ROI para programação matemática, optimx para otimização com não ou Restrições de caixa), mas ainda estão incompletas e não possuem documentação. Existe uma lista mais exaustiva na visão da tarefa Otimização. Se você não está familiarizado com eles, sugiro verificar os mesmos na seguinte ordem. Optim será suficiente para a maioria das suas necessidades de otimização, mas você pode querer recorrer a DEoptim para problemas com muitos extremos locais. Para problemas não lineares com restrições não-caixa (ou seja, restrições especificadas por várias funções, com igualdades ou desigualdades, em vez de limites superiores e inferiores), use Rsolnp. Se o problema for grande e linear ou quadrático, você quer tentar Rglpk ou quadprog em vez disso: eles serão muito mais rápidos, mas pode ser complicado escrever o problema em forma de matriz. Alguns desses solucionadores têm limitações. Por exemplo, lpSolve impõe que todas as variáveis ​​não sejam negativas (é na documentação, com um ponto de exclamação, mas é fácil de ignorar - o Rglpk é o mesmo comportamento padrão, mas pode ser alterado), o quadprog só funciona para Problemas estritamente convexos (a forma quadrática deve ser definida de forma positiva, mas se você precisar adicionar variáveis ​​lentas para transformar algumas das restrições, você acaba com uma matriz semi-definida positiva e não funciona mais - esta é uma séria limitação) As restrições de integridade só podem ser impostas a alguns dos solucionadores lineares. Exceto pelos solucionadores não-lineares (e Rglpk, para o qual você pode dar um arquivo de texto), não é possível especificar os problemas de forma legível por humanos: apenas matrizes. Se o seu problema não é linear, mas pode ser facilmente convertido em um problema linear, você deve fazer a transformação. Algumas das transformações (por exemplo, separar o valor positivo e negativo de um número para expressar seu valor absoluto) são fáceis, mas outras são mais complexas, demoradas e propensas a erros (por exemplo, converter a queda esperada em uma quantidade linear, ou Convertendo restrições quadráticas em restrições semi-definidas). Exemplo: Regressão A regressão linear é um problema de otimização: estamos procurando o valor de b que minimiza a soma residual de quadrados. Vamos comparar o problema de otimização com a regressão. Exemplo: regressão restrita A reformulação do problema de regressão como um problema de otimização permite que você adicione facilmente restrições lineares. Por exemplo, você pode querer que os coeficientes da regressão toquem até 1. Exemplo: regressão cuantitativa O problema de encontrar a mediana de um conjunto de números x1. Xn pode ser formulado como um problema de otimização não-linear: pode ser reformulado como um problema linear, substituindo os valores absolutos pela soma de suas partes positiva e negativa. Vamos verificar um exemplo. Isso pode ser generalizado para outros quantiles: em vez de usar a linha tracejada simétrica abs (x-mu) como uma função de perda, podemos usar uma linha quebrada assimétrica, com inclinação tau se x-mu0 e 1-tau de outra forma, com tau Em 0,1. A mediana é obtida para tau12. Nós também podemos usar essa linha quebrada assimétrica como uma função de perda ao calcular uma regressão: quando tau12 (mediana), esta é a regressão L1 e, em geral, é chamada de regressão quantile. (Uma palavra de cautela: você não deve usar lpSolve exatamente dessa maneira. Ele impõe que todas as variáveis ​​sejam positivas, incluindo o quantile. Nossos exemplos funcionam apenas porque os quantiles são positivos.) Algoritmos Gradient descent O problema de encontrar o mínimo de Uma função f (x) pode ser interpretada geometricamente da seguinte maneira: se f representa a altitude em uma paisagem, minimizar f significa encontrar o vale mais baixo. Um algoritmo direto vem à mente: basta descer. Mais formalmente, comece com uma hipótese inicial x da solução, calcule a derivada (também chamada de gradiente) de f para encontrar a direção da inclinação mais inclinada (para baixo), e dê um passo nesta direção para quando você não pode mais encontrar uma queda direção. Você deve escolher o tamanho do passo de antemão, mas você pode querer que ele dependa da norma do gradiente. Nelder-Mead Se você não conhece a derivada da função (ou se não for diferenciável), você pode modificar o algoritmo de descida do gradiente da seguinte maneira. Comece com um julgamento inicial x. Escolha uma direção ao acaso, entre as coordenadas n, avance e retroceda nesta direção e compare os valores de f: f (x), f (xh), f (x-h). Se um dos novos valores for melhor que o atual, mude para esse ponto, caso contrário, não se mova. Iterate até a convergência. O algoritmo pode ser melhorado alterando o tamanho do passo: aumentá-lo (digamos, por 10) quando você pode se mover, diminuí-lo quando não o faz (porque quando você não pode se mover, o mínimo provavelmente está próximo e você pode estar pisando sobre ele) , E pare quando o tamanho da etapa é muito pequeno. Você pode usar um tamanho de passo diferente para cada coordenada, para evitar problemas se suas escalas forem diferentes. Os pontos xh, xh, em torno de x em todas as direções, formam uma espécie de bola (quadrada): o algoritmo apenas deixa a bola rolar para baixo, e usa uma bola menor, para uma melhor precisão, quando fica preso sobre um vale muito pequeno para Para explorar. Na dimensão n, essa bola quadrada tem 2n pontos (o hipercubo tem 2n vértices, mas apenas usamos os pontos no centro das facetas). O algoritmo de Nelder-Mead usa uma idéia semelhante, mas com uma bola triangular (tetraédrica) ligeiramente mais econômica: ela tem apenas n1 pontos. Gradiente estocástico Muitas vezes, a função a minimizar é uma soma, com um termo para cada observação. Neste caso, você pode processar as observações uma a uma (algoritmo on-line): computa o gradiente do termo correspondente à observação atual, move-se em sua direção (use um tamanho de passo menor do que você faria para o gradiente completo) e continue Com o próximo termo. Gradiente de conjugação Você pode notar que a descida de gradiente às vezes oscila em torno da solução, ou se move em ziguezague antes de atingir o melhor. Isso pode ser corrigido movendo-se, não na direção do gradiente, mas na direção de alguma combinação linear do gradiente e da direção anterior. Isso pode ser interpretado como uma espécie de inércia: nós giramos em parte, mas não completamente, na direção do gradiente, o Hessiano e suas aproximações. O algoritmo de descida de gradiente usou apenas a primeira derivada (ou seja, aproximou a função para minimizar por uma linha reta ). Em vez disso, podemos aproximar a função pela sua segunda expansão de Taylor: a aproximação é uma função quadrática e (desde que seja definida positivamente), ela tem um extremum. Isso requer a segunda derivada (matriz Hessiana) e funciona razoavelmente bem em baixas dimensões. Na verdade, é o método Newtons, usado para resolver f (x) 0. Mas há um grande problema com o hessian: seu tamanho. Se houver n parâmetros para estimar, o hessian é uma matriz nn - quando n é grande, isso não é gerenciável. Precisamos encontrar uma aproximação desta matriz que não requer a computação e o armazenamento de valores n2. Se a função a minimizar é uma soma de quadrados, os cálculos podem ser simplificados pela aproximação do hessiano (Gauss-Newton): O passo h é escolhido de modo que S (bh) 0: Para evitar problemas ao inverter a matriz, o Levenberg - O algoritmo Marquardt encolhe-o em direção à identidade (isto é semelhante à regressão do cume): quando lambda é grande, esse é realmente um passo na direção do gradiente: é uma mistura de descida gradiente e Gauss-Newton. No caso geral, para evitar a computação, armazenar e inverter o Hessiano, queremos uma matriz B, de modo que haja muitas opções possíveis. Um tipicamente começa com uma extimação inicial (digamos, B0I) e atualiza uma estimativa do hessiano à medida que o algoritmo progride para o extremum, adicionando uma matriz fácil de calcular, e. Uma matriz de classificação 1 (as matrizes de classificação 1 podem ser escritas como o produto de dois vetores ab). Por exemplo, o algoritmo BFGS usa duas matrizes de classificação 1: é possível acompanhar uma aproximação do inverso de B ao mesmo tempo. O algoritmo L-BFGS (low-memory BFGS) apenas mantém as últimas atualizações L: existem apenas 2 vetores para armazenar. Otimização restrita: multiplicadores de Lagrange O problema de otimização restrita pode ser substituído (na maioria das vezes) pela condição de primeira ordem, ou seja, queremos encontrar (x, lambda) de modo que isso possa ser implementado da seguinte forma. No entanto, não temos certeza de obter o Mínimo: pode ser um mínimo local ou, uma vez que é apenas uma condição de primeira ordem, um máximo ou um ponto de sela. Observar as condições da segunda ordem daria mais informações, pelo menos se o Hessian for reversível. Condições de KarushKuhnTucker Os multiplicadores de Lagrange lidam com restrições de igualdade. Quando também temos restrições de desigualdade, as coisas se tornam mais complicadas. A condição necessária para um extremum torna-se. A última condição é problemática: diz que para cada restrição de desigualdade oi (x) 0, oi (x) 0 e a restrição é vinculativa e oi aparece na primeira equação ou oi (x ) 0, e a restrição não é vinculativa, mui0 e oi desaparece da primeira equação. Determinar qual restrição é vinculativa é um problema combinatório, melhor abordado por algoritmos combinatórios, como o algoritmo simplex. Programação linear, interpretação geométrica e algoritmo simplex O problema de otimização (x, b, c são vetores, A é uma matriz) pode ser interpretado da seguinte forma. As restrições definem uma interseção de meia-espaços e formam um poliedro. As curvas de nível (hipersuperfície) da função objetiva são, na verdade, linhas retas (hiperplanos), paralelas entre si, queremos encontrar aquele com maior valor, entre aqueles que cruzam o poliedro: isso acontecerá em um vértice do poliedro. Este é um problema combinatório: há um número finito (mas muitas vezes muito grande) de vértices, e temos que encontrar aquele que maximiza o objetivo. O algoritmo simplex procederá da seguinte forma: comece com um vértice do poliedro, encontre uma borda em cuja direção o objetivo aumenta, siga essa borda até o próximo vértice e continue até que você não consiga mais encontrar essa borda. Para isso, precisamos de uma maneira de descrever vértices e bordas que ligam dois vértices. O problema de otimização pode ser reescrito da seguinte maneira, usando variáveis ​​lisas (substituimos A x lt b com A x xS b, xS 0). (As restrições de desigualdade são bastante irritantes, mas xS 0 é absolutamente necessário: garante que os pontos estejam dentro do poliedro, não fora.) Seja (B, N) uma partição da matriz (A, I), de modo que B seja inversível . As soluções com xN0 correspondem a vértices e são fáceis de descrever: o objetivo também é muito simples: o algoritmo é o seguinte: comece com uma partição (B, N) (por exemplo, B pode corresponder às variáveis ​​folgadas que adicionamos) (ie Um vértice no poliedro), tente mudar uma coluna entre B e N para aumentar o objetivo (isto corresponde a mover-se ao longo de uma borda do poliedro) até que você não consiga mais. (Na verdade, você não precisa examinar todos os pares: para cada variável em N, tente incluí-lo o máximo possível, sem violar as restrições: de (), uma das variáveis ​​em B será então 0 - isso é O que você pode remover). Programação linear e dualidade Seja x uma solução de Nós podemos encontrar um limite inferior no objetivo cx, observando uma combinação linear das restrições, yb, para alguns anos. Mas y b y A x, e y A x lt c x desde y A lt c (desde x 0, a direção da desigualdade é preservada). Em outras palavras, qualquer solução viável é um limite inferior. O problema inicial é chamado de problema primordial, e o novo, o problema duplo. Acontece que não é apenas um limite inferior: para as soluções ótimas, o valor do objetivo é o mesmo. Isso nos dá uma maneira fácil de verificar se uma solução viável de um problema de otimização linear é o ótimo: se encontrarmos soluções viáveis ​​x e y dos problemas primordiais e duplos, com os mesmos valores objetivos cxby, então são soluções ótimas . Se o dual for mais fácil de resolver, você pode primeiro resolvê-lo e usar a solução para ajudar a resolver o problema primordial. Alguns algoritmos tentam resolver os problemas primitivos e duplos ao mesmo tempo, cada um ajudando a resolver o outro. A noção de dualidade pode ser generalizada para problemas de otimização arbitrária, mas o fato de que os objetivos, nas soluções ótimas, são iguais, é (muitas vezes, mas) nem sempre verdadeiro. Métodos baseados em gradientes de gradiente reduzido generalizado podem ser usados ​​para resolver problemas gerais de otimização com restrições de igualdade da seguinte maneira. Linearize as restrições usá-los para expressar algumas das incógnitas como uma função dos outros (apenas um sistema linear a ser resolvido) resolver o problema irrestrito resultante com o algoritmo de gradiente iterar até a convergência. Se houver também restrições de desigualdade, as coisas se tornam mais complicadas, mas podemos adaptar o algoritmo simplex. Primeiro, para simplificar o problema, use variáveis ​​lisas para substituir as restrições de desigualdade com restrições de limite inferior ou superior. Em cada etapa do algoritmo, podemos linearizar as restrições de igualdade e reduzir o número de variáveis: os problemas resultantes têm um objetivo não-linear, mas restrições lineares. Começando com uma solução viável, podemos usar algum método baseado em gradiente para avançar em direção à solução e parar quando nos encontrarmos com o limite. Uma vez que estamos no limite, algumas das restrições de desigualdade são ativas (ou vinculativas), ou seja, igualdades. Tal como no método simplex, podemos tentar encontrar quais as desigualdades a serem ativadas ou não para melhorar a função objetiva. Métodos do ponto interior O algoritmo simplex funciona bem, mas explora a superfície do poliedro definido pelas restrições - em alta dimensão, a superfície pode ser muito grande, em comparação com o interior do poliedro (esta é a chamada maldição de dimensão). Os métodos de ponto interior tomam um corte curto dentro do poliedro. Para o problema de otimização, as condições de primeira ordem (Kuhn-Tucker) são. Podemos tentar resolvê-las seguindo o gradiente, que define um caminho de uma solução viável para o extremum ou um ponto no limite - mas quando nos encontramos com o Limite do domínio, esse ponto não é o extremum desejado: o trabalho não está concluído. Em vez disso, podemos seguir outro caminho, por exemplo, as soluções para valores progressivamente menores de tau0. Não precisamos da solução exata de cada um desses problemas intermediários: uma solução aproximada é suficiente. Programação quadrática sequencial (SQP) Podemos rolar nosso próprio otimizador não linear e constrangido. Pode soar como uma ordem alta, mas na verdade é bastante fácil. Queremos resolver o problema onde f, g e h são funções suaves. Se estivéssemos na dimensão 1, tentando minimizar f (x) sem restrições, começamos com um julgamento inicial x, aproximamos f por sua expansão de Taylor de segunda ordem, minimizamos e começamos novamente com o novo valor para x, até convergência. Na dimensão n, com restrições, podemos fazer a mesma coisa: comece com um palpite inicial x, substitua o objetivo f por sua expansão de Taylor de segunda ordem, substitua as restrições g e h pela sua expansão Taylor de primeira ordem, resolva o programa quadrático resultante , Comece novamente com o novo valor para x e continue até a convergência. Isso é chamado de programação quadrática seqüencial. Permita-nos usar esta função para resolver o seguinte problema de entropia máxima. Aqui está outro exemplo. Temos uma matriz nn, conhecemos a soma das linhas, a soma das colunas, conhecemos alguns de seus elementos. Preencha os valores faltantes o mais uniformemente possível, ou seja, preencha os valores em falta de modo a maximizar a entropia - de forma equivalente, para minimizar a divergência de Kullback-Leibler com a distribuição uniforme. O SQP funciona bem para problemas convexos (problemas estritamente convexos, para esta implementação, uma vez que contamos com quadprog). Você pode preferir Rsolnp, que também irá funcionar bem em muitos problemas não convexos. Algoritmos estocásticos Os algoritmos anteriores são limitados a problemas bem comportados: funcionam bem para problemas convexos, para os quais não existem extremos locais que nos enganam. Aqui estão alguns algoritmos de otimização mais robustos para extremos locais. Como eles não podem lidar com restrições, você pode convertê-los em penalidades (restrições suaves). O recozimento simulado explora o espaço viável, aleatoriamente, não diferente da descida gradiente, mas nem sempre em declive: para evitar extremos locais, às vezes aceita soluções mais do que as atuais. A probabilidade de aceitar uma solução pior do que a atual depende de quão ruim é essa solução e a probabilidade diminui progressivamente à medida que o algoritmo avança. Pode ser muito lento. A aceitação de limite que aceita é semelhante, mas a decisão de aceitar uma solução pior do que a atual é determinista, com base em um limite que diminui à medida que o algoritmo avança. A evolução diferencial é um algoritmo baseado em população: acompanhamos uma população de soluções potenciais e misturamos, em cada etapa, para criar a próxima geração. Se x1, x2, x3 são elementos da população atual, as criações são da forma. A otimização do enxame de partículas é outro algoritmo baseado na população, no qual as soluções se movem tanto na direção do gradiente quanto em relação à outra. Os algoritmos genéticos também podem ser usados, mas a maneira como eles combinam soluções (crossover) funciona melhor se as coordenadas forem independentes ou em uma ordem significativa. Eles podem ser melhorados adicionando uma pesquisa local após cada etapa. Rumo a uma interface mais fácil de usar Reescrevendo um problema de otimização em um problema quadrático (por exemplo, livrar-se dos valores absolutos, como no nosso exemplo de regressão quantile) e depois escrever as matrizes correspondentes é fácil, mas extremamente complicado. A situação não é diferente da dos modelos de regressão: o software arcaico incapaz de lidar com variáveis ​​qualitativas exigia que o usuário criasse a matriz do modelo, com variáveis ​​dummy, à mão. Os usuários da Matlab já podem especificar problemas de otimização de forma fácil de usar. Podemos ter algo parecido com R. Queremos poder especificar problemas de otimização, p. Ex. do seguinte modo. Não é tão difícil quanto parece. (O código abaixo é apenas uma prova de conceito: não foi fortemente testado, é conhecido por falhar em alguns casos, é limitado a alguns tipos de problemas, e é muito lento.) As incógnitas são apenas cordas, com um Classe específica, para que possamos sobrecarregar as funções e operadores que precisamos. As funções - som compilam expressões cada vez mais complexas, como cordas. As funções maximizar e minimizar, e os operadores lt, assumir uma expressão (uma string), analisá-la (usando yacas), extrair as partes lineares e quadráticas (no caso de um problema linear ou quadrático) e armazená-las em variáveis ​​globais, Que são eventualmente utilizados pela função de resolução. Funções como abs ou CVaR adicionam novas variáveis ​​e são substituídas por expressões lineares. Isso é válido desde que o problema permaneça convexo, mas não comprovo que seja o caso. A parte complicada é converter as expressões que temos (como strings) nas matrizes esperadas por quadprog ou Rglpk. Confio no Maxima para esta tarefa (talvez seja necessário instalá-lo primeiro) e se comunicar com ele através de pipes nomeados (você precisa de um sistema operacional que forneça pipes nomeados). Exemplos de otimização de portfólio Para os exemplos, usaremos os retornos semanais para um punhado de ações. Para verificar como as coisas se dimensionam quando o universo é maior, aqui está um conjunto de dados mais realista. Igual-ponderado O problema de otimização de portfólio é o problema de encontrar os pesos ótimos de um portfólio, ou seja, quanto você deve investir em cada ativo para maximizar uma quantidade desejável (muitas vezes, uma medida de retorno ajustado ao risco). Se você não tem nenhuma informação sobre os ativos (ou, de forma mais realista, qualquer informação confiável), você pode atribuir o mesmo peso a cada ativo: isso maximiza a entropia (uma medida de diversidade) dos pesos. Variação média As carteiras de variância média maximizam os retornos esperados ajustados ao risco da carteira. O ajuste de risco depende da aversão ao risco do investidor (informalmente, isso corresponde a lambda, na fórmula). Como medida de risco, podemos usar a variância dos retornos da carteira, mas há muitas outras opções. Variação mínima Em vez de analisar os retornos ajustados ao risco, podemos apenas analisar o risco - é muito mais fácil prever o risco futuro do que os retornos futuros. Fronteira eficiente Existem várias maneiras de identificar as carteiras na fronteira eficiente: correspondem a minimizar o risco de retorno esperado fixo esperado, maximizando os retornos para um orçamento de risco fixo e maximizando os retornos ajustados ao risco. Infelizmente, à medida que você adiciona mais restrições (totalmente investidas, não há vendas curtas, limites de peso para cada setor, limites de peso para cada ativo, limite de número de ativos, tamanhos de lote, etc.), a forma da região viável muda e precisa Não permanecem convexos: esses problemas não são mais garantidos para serem equivalentes. Cartas aleatórias Uma maneira muito ingênua de encontrar um portfólio (quase) otimizado, para uma função objetiva arbitrária, seria levar muitas carteiras ao acaso e manter a melhor. Em primeiro lugar, parece uma idéia muito ruim: aparentemente, apenas amostras de carteiras em torno do portfólio igual ponderado. Mas há muitas coisas que estamos fazendo de errado. Primeiro, se tomarmos números distribuídos uniformemente e dividi-los pela sua soma, não temos números uniformemente distribuídos na soma simplex (w) 1: há uma tendência para o centro do simplex. Ele desaparece se usarmos uma distribuição exponencial em vez disso: agora estamos muito mais próximos da fronteira eficiente. Nós realmente não queremos amostrar uniformemente do simples: as carteiras ótimas tendem a estar em algum lugar no limite. Tomar algum poder dos pesos irá polarizar os dados para os vértices e as bordas. (O valor é um pouco alto demais, para que possamos ver o enredo o que realmente acontece). Poderíamos melhorar ainda mais usando sequências de baixa discrepância. Com mais ações, você pode querer aumentar o expoente, mas não muito, caso contrário, a maioria das carteiras estão concentradas em uma única ação. Restrições longas-curtas O portfólio sem restrições de curto e longo prazo tem uma alavancagem excessiva. Nós podemos controlar a alavancagem da mesma forma que implementamos a regressão de cuantil: escreva os pesos do portfólio como wi ai-bi, com a e b positivo. Custos de transação Os custos de transação podem ser adicionados como uma penalidade para a função objetivo. O mais fácil de resolver é uma penalidade L2: o problema permanece quadrático. Mas uma penalidade linear é mais realista. Podemos eliminar o valor absoluto como de costume, escrevendo seu argumento como uma diferença de dois números. Carteira Tangente (Rácio Máximo de Sharpe) Podemos primeiro calcular todas as carteiras na fronteira eficiente e, em seguida, encontrar a tangente entre elas. Mas isso é uma grande quantidade de cálculos se você quiser apenas um portfólio (tanto mais quando há muitos ativos). Alternativamente, podemos usar um otimizador não-linear (à primeira vista, maximizar a relação Sharpe não parece um problema quadrático). Mas não é um problema convexo: não há garantia de que a solução que obtemos seja um máximo global. Acontece que o problema de encontrar o portfólio tangente pode ser reformulado como um problema quadrático, como segue. A carteira tangente é também o portfólio máximo de taxas de Sharpe, onde a relação Sharpe é w mu sqrt (w V w), entre carteiras totalmente investidas (os pesos devem somar até 1). Deixe-nos remover a restrição de que os pesos somam até 1. Não existe mais uma solução única para o problema: uma vez que a proporção de ações em constante mudança quando multiplicamos os pesos por um número diferente de zero (é homogêneo de grau 0) As carteras máximas de taxa Sharpe formam uma linha - uma vez que conhecemos um portfólio, podemos obter os outros, multiplicando-o por um escalar. Para ter uma única solução, podemos impor uma condição sobre os pesos. Por exemplo, podemos pedir que o numerador da relação Share seja 1. Então, temos que maximizar 1qq (w V w), isto é, minimizar w V w: esse é um problema quadrático. Otimização baseada em cenários: CVa mínima O valor condicional em risco (CVaR), também chamado de déficit esperado (ES), é a perda esperada, uma vez que a perda está além de algum limite. O limiar é geralmente algum quantile da distribuição dos retornos, e. O 5 quantile, ou o 1 quantile. Podemos usar o déficit esperado como medida de risco. Se soubéssemos da distribuição dos retornos, isso seria simplesmente um problema de otimização não-linear. No entanto, os retornos não são gaussianos. (Podemos usar outras distribuições paramétricas.) Em vez de uma distribuição paramétrica, podemos usar a distribuição empírica dos retornos. Primeiro, precisamos expressar o déficit (amostra) esperado como um problema de otimização. É o mínimo, sobre você, de O problema de otimização torna-se um pouco confuso (se você comete um erro em algum lugar, por exemplo, com o sinal das variáveis ​​lentas, o erro é extremamente demorado para rastrear). Para garantir que estamos realmente minimizando o déficit esperado, comparemos com uma otimização mais direta. Da mesma forma, podemos adicionar uma restrição ao CVaR. Otimização baseada em cenários: VaR O valor em risco (VaR) é apenas um quantile da distribuição de retornos - mas é expresso como uma perda, de modo que o signo é diferente. Pode ser expresso da seguinte forma, uma vez que este é um mínimo, ele pode ser usado na função objetiva de um problema de otimização, como fizemos para o CVaR. Infelizmente, as funções do indicador (que podem ser codificadas com variáveis ​​binárias) tornam o problema de otimização (não convexo e) bastante difícil de resolver. Podemos usar algum otimizador robusto, p. DEoptim. Branch-and-bound: variáveis ​​binárias e restrições de cardinalidade Adicionando a restrição de que algumas das variáveis ​​são binárias, isto é, só pode tomar dois valores, 0 ou 1, torna o problema ainda mais combinatório. Se houver n tais variáveis ​​binárias, podemos resolver os 2n problemas correspondentes a todos os seus valores possíveis. Isso é demais, é claro, mas podemos reduzir o número de problemas a serem solucionados, organizando-os em uma árvore, encontrando um limite no valor de cada subárvore e podando todas as sub-estruturas da seguinte forma. A raiz da árvore corresponde ao problema sem restrições: as variáveis ​​binárias são apenas limitadas para estar em 0,1, mas elas não precisam ser inteiras. Existem dois nós infantis, cada um adicionando uma restrição na primeira variável binária: é 0 ou 1 (as demais variáveis ​​permanecem em 0,1). A próxima camada da árvore (4 nós) adiciona restrições na segunda variável, e assim por diante. Estamos à procura da folha com a melhor solução. Uma vez que os nós têm restrições menos rigorosas do que as folhas, sua solução é melhor, mas nunca pior, que as folhas abaixo delas: se o valor de um nó é pior do que a melhor solução de folha encontrada até agora, não há necessidade de explorar a Subtree, e pode ser podada. No exemplo a seguir, consideramos o problema de encontrar a variância mínima, o portfólio de longo prazo, com no máximo 5 ativos. The problem can be written as Let us first write functions to add constraints and solve the problem (so that the code can be reused with other solvers). Branch-and-bound: Integer variables and lot sizes The same idea can be used to handle integrality constants: at each node, we split the tree into 3 subtrees, corresponding to the constraints xiv (where v is some integer value, e. g. the integer closest to the solution of the unconstrained problem), xi v1 and xi lt v-1. The tree can be much larger than in the binary case: only when we add an equality constraint does the number of variables to decide on decrease. (In most cases, the xi are bounded, so that the tree is finite.) The algorithm can be improved: you can split the nodes in 2 rather than 3, you can carefully choose the variable to split on, you can use better heuristics to find a good upper bound on the minimum, you can add constraints to shrink the set of feasible solutions (branch-and-cut). Equal contribution to risk The risk of a portfolio, is homogeneous of degree 1, and can therefore be decomposed as where the marginal contribution to risk (MCTR) of asset i can be computed as Let us check on an example: It is easy to find portfolios with equal marginal contribution to risk. It is not really an optimization problem, but just a system of equations to solve. If r is the vector of desired marginal contributions to risk (up to a multiplicative constant), we want w (and lambda) such that In a risk parity portfolio, the assets have the same contribution to risk (the contribution to risk is wMCTR). They are a special case of risk budgeting portfolios, where the contribution to risk of each asset is imposed. It is still a system of equations to solve, but it is not linear: if ri is the desired contribution to risk of asset i, we want to find w so that where the risk is the sum of the contributions to risk. This can be written as where. is the elementwise product. (It is a quadratic equation: no easy solution.) We can use a non-linear solver. Since the problem is not convex, you may want to try other optimizers (e. g. DEoptim). Conclusion What we talked about We have presented the algorithms behind commonly-used optimization routines. They fall into three broad categories: gradient-like methods, that try to find a direction in which the objective function is better (with many variants, some eschewing the gradient (Nelder-Mead), some using a biased gradient (conjugate gradient), some using the hessian, some approximating the hessian (L-BGFS), some using the specific form of the objective function to simplify the computations (Gauss-Newton, Levenberg-Marquardt)) combinatorial methods, that explore on the frontier of the feasible set, from vertex to vertex (or from facet to facet), to improve the objective function (simplex, generalized reduced gradient) interior point methods, that regularize the Kuhn-Tucker conditions g lambda 0 into g lambda tau, and let the regularization parameter tau decrease. We have presented some code to add binary or integral constraints to an arbitrary optimization problem and code to allow us to enter optimization problems in a human-readable form. We have given a few portfolio optimization examples: minimum variance, mean-variance, CVaR, VaR, prescribed contribution to risk, using a variety of optimization algorithms, including random portfolios. We saw that, for real-world problems, different optimizers may give different results: it is safer to use several optimizers (some lack robustness, some lack speed, some are user-unfriendly and their use is therefore bug-prone), check that the constraints are satisfied (especially if you have to transform the problem by hand to give it to the optimizer) and compare with some base-line algorithm (e. g. random portfolios). What we did not talk about I focused on the algorithms, without stressing how careful one should be when using them in a financial context. You need to check if the purportedly optimal portfolios are indeed close to optimal, out-of-sample -- and you need to clearly define what you mean by optimal. This will not only depend on the optimization problems, but also on the estimators of variance and returns used. You should check how sensitive those optimization problems are to their inputs. You should also carry out a complete backtest, to check how consistent the resulting portfolios are over time: is their out-of-sample performance independent of the market regime do they generate an excessive turnover I did not mention the use of copulas, volatility models, (semi-)parametric estimators of VaR and CVaR, spectral risk measures, drawdown. I intended to but did not mention second order cone programming and semi-definite programming, which generalize quadratic programming, and can be used for quadratic constraints and robust optimization (i. e. situations where you do not have a single number for the variances and expected returns, but intervals). There is an Rcsdp package, but the documentation is scarce (only one example), the error messages cryptic, and the licence non-standard.

No comments:

Post a Comment