Encontre o melhor período para investir em um fundo de índice S & P500

8

Aqui estão os retornos anuais de um fundo hipotético de índice de ações S&P 500 para cada ano civil de 1928 a 2017, expresso como multiplicador. Então, em 1928, você pode dizer "o índice subiu 37,88%", que eu representei aqui por 1,3788.

1.3788, 0.8809, 0.7152, 0.5293, 0.8485, 1.4659, 0.9406, 1.4137, 1.2792, 0.6141,  1.2521, 0.9455, 0.8471, 0.8214, 1.1243,  1.1945, 1.138, 1.3072, 0.8813, 1,  0.9935, 1.1026, 1.2178, 1.1646, 1.1178,  0.9338, 1.4502, 1.264, 1.0262, 0.8569,  1.3806, 1.0848, 0.9703, 1.2313, 0.8819,  1.1889, 1.1297, 1.0906, 0.8691, 1.2009,  1.0766, 0.8864, 1.001, 1.1079, 1.1563,  0.8263, 0.7028, 1.3155, 1.1915, 0.885,  1.0106, 1.1231, 1.2577, 0.9027, 1.1476,  1.1727, 1.014, 1.2633, 1.1462, 1.0203,  1.124, 1.2725, 0.9344, 1.2631, 1.0446,  1.0706, 0.9846, 1.3411, 1.2026, 1.3101,  1.2667, 1.1953, 0.8986, 0.8696, 0.7663,  1.2638, 1.0899, 1.03, 1.1362, 1.0353,  0.6151, 1.2345, 1.1278, 1, 1.1341,  1.296, 1.1139, 0.9927, 1.0954, 1.1942

Fonte: https://www.macrotrends.net/2526/sp-500-historical-annual-returns

Desafio

Dados como entradas:

  • a matriz de retornos anuais (mas consulte a Regra 2. abaixo)
  • uma matriz de números positivos (os valores a serem investidos em cada ano do período de investimento)X1K90

escreva um programa ou função que produza o que teria sido o "melhor" período do ano consecutivo de para investir os valores em , onde:KX

  • cada valor é investido no início de um ano.
  • tudo o que resta depois de cada ano é reinvestido no início de cada ano subseqüente.
  • "melhor" significa a maior quantidade no final do período do anoK

Regras

  1. Isso é , portanto, o menor número de bytes em cada idioma vence. Aplicam-se regras padrão. Explicações encorajadas.

  2. Se você não gostar da maneira como representei a matriz de retornos anuais, poderá alterá-los para qualquer outra matriz de 90 números que preferir.

  3. Você pode produzir o melhor período do ano qualquer maneira consistente (por exemplo, indexado a 0 ou 1, o primeiro e / ou o último ano a investir, etc.), mas precisa dizer o que sua produção representa se não for ' t óbvio.K

  4. Em caso de empate, dê uma ou todas as respostas corretas.

Exemplo de cálculo

Suponha que .X=[10000,20000,30000]

Se você tivesse investido esses valores em 1928, 1929 e 1930 (os índices 1, 2 e 3), você terminaria com 42743.10. Triste.

Mas se você tivesse investido esses valores em 2014, 2015 e 2016 (os índices 1, 87, 88 e 89), teria terminado com 66722,66. Um pouco melhor.

Acontece que o melhor período de três anos para investir esses valores teria sido 1995, 1996 e 1997 (índices 1, 68, 69 e 70), resultando em 91942.91. Agradável.

Casos de teste

Primeiro ano do período ideal, indexado em 1

[ 1, 2, 3 ]                          ->  68
[ 1 ]                                ->   6
* any array of length 90 *           ->   1
[ 1, 1 ]                             ->  27
[ 1, 2 ]                             ->   8
[ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ]  ->  62
[ 1, 2, 3, 4, 5, 4, 3, 2, 1 ]        ->  64
* 1 repeated 20 times *              ->  53
ngm
fonte
A regra 2 diz que podemos substituí-los por qualquer outra matriz de 90 números. Presumo que não é válido substituí-lo por uma matriz que é 1 seguida por 89 0s, para que 1 seja sempre a resposta correta? Ou você quis dizer "pegue a entrada que quiser, mas o número que obtém a saída precisa corresponder aos casos de teste"?
Kamil Drakari #
1
@KamilDrakari, você pode fazer qualquer transformação de 1 a 1 que quiser. Você precisa terminar com a resposta correta real. A idéia é que alguém possa preferir retornos cumulativos, ou esses retornos menos 1. Está aí para flexibilidade. Mas se também houver alguma oportunidade oculta de golfe, que assim seja.
ngm
@ngm ok, então é "você pode codificar essa entrada da maneira que desejar" em vez de "sua resposta precisa trabalhar apenas para um valor específico para essa entrada e você pode escolher o que é isso"
Kamil Drakari
@KamilDrakari sim, embora não seja exatamente do jeito que você quiser - você ainda está limitado a uma matriz com 90 elementos.
ngm
"Então, em 1927, você pode dizer ..." - Eu acho que você quer dizer 1928.
Jonathan Allan

Respostas:

6

Geléia , 9 bytes

PÐƤ⁹L¤ƤḋM

Um link diádico que gera uma lista de todos os índices iniciais máximos baseados em 1.

Experimente online!

(ou ṡL}PÐƤ€ḋM)

Quão?

PÐƤ⁹L¤ƤḋM - Link: list of returns, list of nominal investments
      Ƥ   - for infixes of (the returns)...
          - ...of length:
     ¤    -               nilad followed by links as a nilad:
   ⁹      -                 chain's right argument (nominals)
    L     -                 length
          - ...do:
 ÐƤ       -        for post-fixes:
P         -          product
       ḋ  - dot-product (each) with (the nominals)
        M - maximal indices
Jonathan Allan
fonte
3

Japt , 25 bytes

ãVl)míV ®rÈ+YÌ *Yg}0
bUrw

Experimente online!

Saída indexada em 0.

Explicação, com Ua lista de retornos e Va lista de investimentos:

ã                       :Get subsections of U
 Vl)                    : with the same length as V
    m                   :For each of those sections
     í                  : pair each element with
      V                 : the corresponding element from V
        ®          0    :Calculate the investment results of each by:
         r        }     : for each year:
          È+            :  add the result of the previous year
            YÌ          :  to this year's investment
               *Yg      :  and multiply by this year's return

b                       :Get the index of
 Urw                    : the maximum

Resposta de trapaça bônus:

Japonês , 13 bytes

OvUÎò3 ®n dÃq

Experimente online!

Leva a lista de retornos como essa matriz , que é uma matriz de 90 cadeias em que cada cadeia contém um número inteiro de base 10 preenchido com 1929 dígitos; Acredito que isso atenda tecnicamente aos requisitos. O link "Experimente" possui apenas o primeiro elemento da lista "retornos" porque a coisa toda quebrou o gerador de link permanente, mas esse é o único que é usado. Você pode colar a coisa toda a partir do pastebin, se quiser.

Explicação:

Como mencionado, apenas o primeiro elemento da matriz "retorna" é realmente usado; todos os outros elementos são 0 no pastebin e ignorados pelo programa. O primeiro elemento é gerado por isso , que pega a representação de sequência de um programa Japt, transforma cada caractere em um número de 3 dígitos e une esses números em uma nova sequência de apenas dígitos. O código que está sendo codificado é este , que é basicamente a minha resposta principal ajustada para codificar os retornos. Então o programa "resposta" é apenas:

  UÎ             :Get the first element
    ò3           :Cut it into slices of length 3
       ®n        :Convert those strings to numbers
          dà    :Convert those numbers to characters
            q    :Join all the characters into one string
Ov               :Execute it as Japt
Kamil Drakari
fonte
Não tenho certeza se a versão de 13 bytes segue as regras padrão (codificar o código real em entradas flexíveis parece uma brecha ), mas eu gosto mesmo assim!
Ng
@ngm Quero dizer, eu chamei de uma resposta fraudulenta e coloquei uma resposta real por um motivo. Eu estava apenas tentando esticar os limites de "qualquer outra matriz de 90 números que você preferir".
Kamil Drakari
2

JavaScript (ES6), 73 bytes

Toma entrada como (annual_returns)(X). O resultado é indexado em 0.

a=>x=>a.map((_,i)=>x.map((c,j)=>(t=(t+c)*a[i+j])>m&&(r=i,m=t),t=0),m=0)|r

Experimente online!

Arnauld
fonte
2

J, 48 bytes

1+[:(i.>./)[:({:@[*{.@[+*/@])/"2[(|.@,."1)#@[]\]

Experimente online!

destroçado

1 + [: (i. >./) [: ({:@[ * {.@[ + */@])/"2 [ |.@,."1 #@[ ]\ ]

como

Pegue a lista de entrada (por exemplo, 123) à esquerda, dados à direita.

#@[ ]\ ] Divida os dados em infixos cujo comprimento corresponde à entrada:

1.3788 0.8809 0.7152
       0.8809 0.7152 0.5293
              0.7152 0.5293 0.8485

[ ,."1 Agora zip cada um desses grupos de 3 com a lista de entrada

1      2      3
1.3788 0.8809 0.7152
       1      2      3
       0.8809 0.7152 0.5293
              1      2      3
              0.7152 0.5293 0.8485

|.@ e inverta-os:

3      2      1
0.7152 0.8809 1.3788

(verb to insert)/"2 Entre os itens de cada grupo compactado de 3, insira o verbo entre parênteses.

3             2             1
        VERB          VERB
0.7152        0.8809        1.3788

({:@[ * {.@[ + */@]) é o verbo inserido, que reduzirá cada item da lista de grupos compactados de três para um número, que é o valor ganho nesse grupo de anos:

          2. plus the first      1. */] = product of right args
             (top) item on left
              +-+     +--------+
              |2|  +  |    1   |
              +-+     |    *   |     
                      | 1.3788 |
             *        +--------+

          0.8809  

          3. Multiply that sum by the bottom
             number on the left.

(i. >./) Pegue a lista assim reduzida e encontre o índice do max.

1 + [: E adicione um

Jonah
fonte
1

Gelatina , 11 bytes

ṡ⁹L¤U×\€UḋM

Experimente online!

O fator de retorno de um depósito é o produto cumulativo dos fatores de retorno nos anos até o final do Kperíodo do ano. Se tivermos permissão para inverter a entrada e gerar um número de ano como 2018- [data de término], a solução de 10 bytes×\⁹L¤Ƥ×S€M funcionará.

ṡ                All overlapping slices of left input of length:
 ⁹L¤               length(right input)
                 Calculate cumulative returns list for each possible year:
    U              Reverse each element of the result
     ×\€           Take the cumulative product
        U          Reverse again
         ḋ      Dot product with the deposits list.
                The final balance when invested in each year.
          M     Get all indices of maximum values
lirtosiast
fonte
ṡL}salva um byte sobre ṡ⁹L¤(minha alternativa 9 Byter, ṡL}PÐƤ€ḋMé efetivamente uma versão mais golfed)
Jonathan Allan
@JonathanAllan Eu ainda estou aprendendo Jelly. Como exatamente funciona-- }é sempre equivalente a ⁹[monad]¤?
lirtosiast
1
Não, não é exatamente equivalente. O }quick trata a mônada à sua esquerda como se fosse uma díade e usa o argumento da direita como a entrada da esquerda para essa díade (não fazendo nada com o argumento da esquerda); portanto, a análise do código que contém L}é como se fosse uma díade, enquanto a análise do código que contém ⁹L¤é como se fosse uma nilada - se você tentar a substituição no código de Erik, ela não funcionará, pois a próxima parte da cadeia é uma díade (enquanto a próxima na sua é uma mônada).
Jonathan Allan
1

Python 2 , 97 bytes

lambda r,v:max(range(len(r)-len(v)+1),key=lambda i:reduce(lambda x,(a,b):(x+a)*b,zip(v,r[i:]),0))

Experimente online!

Devoluções - 0indexadas

TFeld
fonte
O último item de rdeve ser 1.1942. Além disso, len(r)é 90.
Erik the Outgolfer
@EriktheOutgolfer Fixed
TFeld
1

05AB1E , 21 20 bytes

Œsgùεø0©\vy`s®+*©]Zk

Muito tempo ..

Indexado a 0.

Experimente online ou verifique todos os casos de teste .

Explicação:

Œ                  # Get all sublists of the (implicit) input-list of stock-changes
 s                 # Swap to take the second (implicit) input-list of investments
  g                # And take its length
   ù               # Only leave sublists of that size
ε                  # Map each to:
 ø                 #  Create pairs with the second (implicit) input-list of investments
  0©               #  Store 0 in the register
    \              #  Discard the 0 from the stack
     vy            #  Loop `y` over the pairs
       `           #   Pop and push both values of the pair to the stack
        s          #   Swap them
         ®+        #   Add the value from the register to the investment amount
           *       #   And multiply it by the current number of the sublist
            ©      #   And then replace the value in the register with this
             ]     # Close both the loop and map
              Z    # Take the max of the mapped sublists (without popping the list)
               k   # Determine the index of that max (and output implicitly)
Kevin Cruijssen
fonte