Então, primeiro: acabei de terminar uma ciência de dados do Thinkful no programa de bootcamp python que deveria levar seis meses, em cerca de quatro meses. Todos os meus projetos principais foram aplicados à negociação de volatilidade; Para encurtar a história, nenhuma das técnicas de ML funcionou e, quanto mais complexa a técnica que eu tentei, pior ela foi. Existe um lugar para a ciência de dados em Python no mundo? Claro. Algumas empresas juram por isso. No entanto, atualmente o R tem muito mais bibliotecas desenvolvidas especificamente para finanças quantitativas, como PerformanceAnalytics, quantstrat, PortfolioAnalytics e assim por diante. Mesmo para tarefas mais básicas de gerenciamento de portfólio, eu uso funções como Return.Portfolio e charts.PerformanceSummary em R, o equivalente ao qual não vi no Python. Embora existam alguns sites com seus próprios dialetos construídos no Python, como quantConnect e quantopian, acho que essa é mais a sua própria marca especial de sintaxe, em vez de ser capaz de criar estratégias de backtest de portfólio de forma livre a partir de pandas.
De qualquer forma, eis o meu portfólio Python do bootcamp que concluí. O fato de a ingestão de dados do Yahoo ter interrompido o índice SHORTVOL significa que os notebooks supervisionados e não supervisionados precisam que seus dados sejam substituídos por aquele no projeto final do capstone. Você pode olhar os cadernos para ver exatamente o que eu tentei, mas para ir direto ao ponto, nenhuma das técnicas funcionou. Florestas aleatórias, SVMs, aumento de XG, UMAP … elas não se aplicam realmente à previsão de retornos. Os recursos que usei foram aqueles que utilizo em minha própria estratégia de negociação, pelo menos alguns deles, por isso não foi um caso de “lixo dentro, lixo fora”. E quanto mais avançada a técnica, piores os resultados. Nas palavras de um parceiro comercial quant sênior: “Auto-ML = auto-falido”. Portanto, quando as pessoas dizem “usamos IA e aprendizado de máquina para gerar retornos superiores”, eles descobriram algo absolutamente espetacular (altamente improvável) ou estão apenas usando os termos mais recentes do hype. Afinal, até a regressão linear pode ser pensada como um modelo de aprendizado.
Mesmo o uso de PCAs de vários recursos da estrutura de termos fez um trabalho pior do que minha estratégia básica de negociação de volatilidade. Obviamente, ficou melhor desde então, à medida que adicionei mais gerenciamento de riscos à estratégia e percebi uma boa parte do movimento de longo volume de coronavírus em março. Você pode se inscrever aqui.
Então, sim, eu codifico em Python agora (se o post anterior não era qualquer indicação, então aqueles que precisam de algum desenvolvimento em Python para trabalhar com quant, se ele usa a pilha numpy / scipy / pandas usual, sinta-se à vontade para entrar em contato comigo) .
Enfim, este post é sobre como adicionar algumas análises de estilo de Corey Hoffstein às estratégias de alocação de ativos, desta vez em R, porque esta é uma técnica que eu usei para um projeto freelancer muito recente para uma empresa de alocação de ativos para a qual atualmente trabalho como freelancer (off e on) . Eu chamo isso de estilo Corey Hoffstein, porque no twitter ele sempre fala sobre analisar o impacto da sorte no tempo. Seu blog na Newfound Research é ótimo para pensar em elementos que não se vê em muitos outros lugares, como analisar estratégias de acompanhamento de tendências no contexto de pagamentos de opções, o impacto da sorte no tempo e vários parâmetros das janelas de lookback etc. .
A idéia rápida é a seguinte: quando você reequilibra um portfólio todos os meses, deseja saber como a alteração dos vários dias de negociação afeta seus resultados. É isso que Walter faz na AllocateSmartly.
Mas uma pergunta mais interessante é o que acontece quando um portfólio é reequilibrado em prazos mais longos – ou seja, o que acontece quando você reequilibra um portfólio apenas uma vez por trimestre, uma vez a cada seis meses ou uma vez por ano? E se, em vez de reequilibrar trimestralmente em janeiro, abril e assim por diante, você reequilibrar em fevereiro, maio etc.?
Este é um pedaço de código (em R, até agora) que faz exatamente isso:
offset_monthly_endpointsEssentially, the idea behind this function is fairly straightforward: given that we want to subset on monthly endpoints at some interval (that is, k = 3 for quarterly, k = 6 for every 6 months, k = 12 for annual endpoints), we want to be able to offset those by some modulo, we use a modulo operator to say “hey, if you want to offset by 4 but rebalance every 3 months, that’s just the same thing as offsetting by 1 month”. One other thing to note is that since R is a language that starts at index 1 (rather than 0), there’s a 1 added to the offset, so that offsetting by 0 will get the first monthly endpoint. Beyond that, it’s simply creating an index going from 1 to the length of the endpoints (that is, if you have around 10 years of data, you have ~120 monthly endpoints), then simply seeing which endpoints fit the criteria of being every first, second, or third month in three.
So here’s how it works, with some sample data:
require(quantmod) require(PerformanceAnalytics) getSymbols('SPY', from = '1990-01-01') > head(SPY[offset_monthly_endpoints(Return.calculate(Ad(SPY)), 3, 1)]) SPY.Open SPY.High SPY.Low SPY.Close SPY.Volume SPY.Adjusted 1993-01-29 43.96875 43.96875 43.75000 43.93750 1003200 26.29929 1993-04-30 44.12500 44.28125 44.03125 44.03125 88500 26.47986 1993-07-30 45.09375 45.09375 44.78125 44.84375 75300 27.15962 1993-10-29 46.81250 46.87500 46.78125 46.84375 80700 28.54770 1994-01-31 48.06250 48.31250 48.00000 48.21875 313800 29.58682 1994-04-29 44.87500 45.15625 44.81250 45.09375 481900 27.82893 > head(SPY[offset_monthly_endpoints(Return.calculate(Ad(SPY)), 3, 2)]) SPY.Open SPY.High SPY.Low SPY.Close SPY.Volume SPY.Adjusted 1993-02-26 44.43750 44.43750 44.18750 44.40625 66200 26.57987 1993-05-28 45.40625 45.40625 45.00000 45.21875 79100 27.19401 1993-08-31 46.40625 46.56250 46.34375 46.56250 66500 28.20059 1993-11-30 46.28125 46.56250 46.25000 46.34375 230000 28.24299 1994-02-28 46.93750 47.06250 46.81250 46.81250 333000 28.72394 1994-05-31 45.73438 45.90625 45.65625 45.81250 160000 28.27249 > head(SPY[offset_monthly_endpoints(Return.calculate(Ad(SPY)), 3, 3)]) SPY.Open SPY.High SPY.Low SPY.Close SPY.Volume SPY.Adjusted 1993-03-31 45.34375 45.46875 45.18750 45.18750 111600 27.17521 1993-06-30 45.12500 45.21875 45.00000 45.06250 437600 27.29210 1993-09-30 46.03125 46.12500 45.84375 45.93750 99300 27.99539 1993-12-31 46.93750 47.00000 46.56250 46.59375 312900 28.58971 1994-03-31 44.46875 44.68750 43.53125 44.59375 788800 27.52037 1994-06-30 44.82812 44.84375 44.31250 44.46875 271900 27.62466Observe como obtemos diferentes datas de término do reequilíbrio trimestral. Isso também funciona semestralmente, anualmente e assim por diante. A única ressalva a esse método, porém, é que, ao fazer uma análise tática da alocação de ativos em R, eu subconjunto por pontos de extremidade. E como eu costumo usar terminais mensais em intervalos de um (ou seja, todos os terminais mensais), é bastante simples para mim incorporar medidas de momento em qualquer período de lookback mensal. Ou seja, 1 mês, 3 meses etc. são todos bastante simples quando se reequilibra todos os meses. No entanto, por exemplo, se alguém fizer um reequilíbrio a cada trimestre e adotar apenas pontos finais trimestrais, obter uma medida de impulso de um mês a cada trimestre exigiria um pouco mais de trabalho. Se você quiser fazer o reequilíbrio trimestral, tranche-o todos os meses, mas também não basta reequilibrar no final do mês, mas reequilibrar várias vezes ao longo do mês, o que exigiria ainda mais meticulosidade.
No entanto, um tipo de segundo método "kludge-y" para fazer isso seria executar o backtest para encontrar todos os pesos e, em seguida, aplicar uma metodologia de codificação semelhante aos * pesos *. Por exemplo, se você tiver uma série temporal de pesos mensais, basta criar um índice que varia de 1 ao comprimento dos pesos, dependendo da frequência com que você deseja reequilibrar, subconjunto para cada mod 3 == 0, 1 ou 2 De maneira mais geral, se você reequilibrar uma vez a cada k meses, criará um índice que varia de 1 ao tamanho do seu índice, se o idioma for base 1 (R) ou 0 ao comprimento n-1, se Python. Então, você simplesmente vê quais índices dão o restante de 0 a k-1 ao usar o módulo K, e é isso. Isso permitirá que você obtenha k diferentes tranches de reequilíbrio, tomando os índices desses pontos de extremidade. E você ainda pode compensar esses pontos de extremidade diariamente também. A ressalva aqui, é claro, é que você precisa executar o backtest para todos os meses individuais e, se tiver uma rotina de otimização complexa, isso poderá levar um tempo desnecessariamente longo. Portanto, qual método você usa depende da tarefa em questão. Esse segundo método, no entanto, é o que eu usaria como invólucro para um algoritmo de reequilíbrio mensal que já existe, como meu algoritmo de alocação de ativos KDA.
É isso neste post. Em termos das coisas que quero construir daqui para frente: gostaria de portar algumas funcionalidades básicas de R para Python, como Return.Portfolio e charts.PerformanceSummary, e quando eu conseguir fazer isso funcionar, para demonstrar como fazer um muito do mesmo trabalho de alocação de ativos que fiz em R ... em Python também.
Obrigado pela leitura.
NOTA: Atualmente, estou procurando uma função em tempo integral para usar minhas habilidades em R (e agora em Python). Se você está contratando ou conhece alguém que não seja, não hesite em entrar em contato comigo no meu LinkedIn.
Relacionado
Se você chegou até aqui, por que não inscreva-se para atualizações do site? Escolha o seu sabor: e-mail, twitter, RSS ou facebook ...