3
\$\begingroup\$

I am creating an investment/betting simulation; since is the first I create , I am sure it can be done better, both from a coding and a simulation point of view.

I would like to ask you what you think and if you can share your experience.

There are 5 main variables that the user has to input:

  • z --> it is my average winning percentage. As discuss later, a random number between 0 and 100 will be generate. If the generated number (x) is greater than (z), then the trade is loss; if x < z, is a win.

  • invest --> how much money invested per trade, es. 10$. In case of a win, the return is always the 70%. i.e. bet 10$, win 7$ (plus the bet)

  • days --> how many days I trade. there is fixed amount of trade per day, which is between 9 and 33

  • simulazioni --> the number of simulations

  • varianza --> is the shifting probability. If varianza is 5% and my percentage (z) is 50%, my actual variance could be either 45% or 55%. This is calculated randomly for each trade.

As you can see from the code at the bottom, the simulation is based on "for loops". The main one is the simulations, second one are the days and the last one calculates if the trading is positive or negative.

There are also dictionaries that I use to collect data from daily profit and total profit (i.e. "datatot"; these dictionaries are used to plot data later on (this bit is not included in the code).

import random
import matplotlib.pyplot as plt
import matplotlib.mlab as mlab
import numpy as np

data=[]
data2=[]
datatot = []
portafoliotot = 0
portafolio = 0
pos= 0 
neg= 0

#input variables
z= input("Percentuale: ")
invest = input("Investimento:")
days = input ("Giorni:")
simulazioni = input("Simulazioni:")
varianza = input("Varianza:")

for simulazione in range(0,int(simulazioni)):

    for giorno in range(0,int(days)):

        portafoliotot = 0 #simulation portfolio
        portafolio = 0 #daily portfolio
        pos = 0 #n of positive trades
        neg = 0 #n of negative trades


        for trade in range(0,int(random.randint(9,33))):

            x=random.randint(0,100) #random number to see if the trade is pos or neg

            calcvarianza = 2 * np.random.rand() - 1 # calculation of (varianza). if positive, is going to be added to (z), otherwise subtracted. this is done for each trade.

            if calcvarianza > 0:
                varianza = - int(varianza)

            if x<(int(z)+int(varianza)): #checking if the trade is pos or neg

                portafolio += (int(invest)/100)*70
                pos +=1 
            else:
                portafolio += -int(invest)
                neg +=1


        portafoliotot += portafolio
        data.append(portafoliotot)
        data2.append(portafoliotot)

    datatot.append(sum(data2))
    data2 = []
\$\endgroup\$
  • \$\begingroup\$ portafolio += -int(invest) why not just -=? Maybe that's just me, but I think that using your native language in code (English isn't native language for me too by the way) is kind a bad decision. For example you may have to show it on a site like this and everybody would understand your code easier if it would be in English. \$\endgroup\$ – user1685095 May 19 '17 at 20:09
  • \$\begingroup\$ Also try to use PyCharm to fix your code formatting. \$\endgroup\$ – user1685095 May 19 '17 at 20:10
  • \$\begingroup\$ If you want to randomly choose True or False instead of if 2 * np.random.rand() - 1 you can just do if random.randbits(1) \$\endgroup\$ – user1685095 May 19 '17 at 20:20
2
\$\begingroup\$

Idiomatic Python suggestions:

  • Use argparse rather than input to set the configuration. It is easy to use, and very powerful.

General suggestions:

  • data and data2 are literally considered the world's worst variable names. Naming is well known to be a hard problem, but it's also a great skill to learn. Naming a thing well gives much needed information to anyone reading the script, including yourself.
  • Comments like "checking if the trade is pos or neg" are code smells which point to an opportunity to extract a class or function.
  • Your program contains many magic values, like 33. Use constants or set them as defaults for arguments to make it clear what these numbers mean.
  • Your program neither prints nor returns anything. In other words it can be replaced by the single line pass.
  • This may sound chauvinist, but use English names for things in your program. The world's developers have avoided localising programming languages for a long time, and in a programming job you are very likely going to be expected to write everything except user interfaces in English. As long as practically every function, class, package and module in the world is named in English, you are going to improve maintainability by using a single language in your programs. Disclaimer: I'm not a native English speaker.
\$\endgroup\$
0
\$\begingroup\$

I don't understand what you're trying to do (for example you counting negative and positive investments but this information isn't used in code), but you can do this more declarative.

Use descriptive function names instead of comments.

def is_trade_negative():
    return rnd.randint(0, 100) < (z + (-varianza if rnd.randbits(1) else varianza))

When you summing current investment into temp variable that has value of previous sum and then store this variable into array what you're doing is accumulative sum. This is what itertools.accumulate from stdlib is for.

Hence you can do something like that.

investments = (
    tuple(itertools.accumulate(
        (invest / 100) * 70 if is_trade_negative() else -invest
        for day in range(days)
        for trade in range(rnd.randint(9, 33))
    ))
    for sim in range(simulations)
)

results = ((sum(inv), inv) for inv in investments)
\$\endgroup\$
  • \$\begingroup\$ This site is Code Review, not Alternate Solutions. \$\endgroup\$ – Nic Hartley May 20 '17 at 0:23
  • \$\begingroup\$ @QPaysTaxes I know that and I think that declarative style is this case is better than imperative. Hence my code. The author asked how to make his code better. Here's the answer. Use itertools.accumulate and comprehension. \$\endgroup\$ – user1685095 May 20 '17 at 0:30
  • \$\begingroup\$ Except, again, this is Code Review, not Alternate Solutions. You've done nothing but say "here's how I would do it". You didn't review the code. \$\endgroup\$ – Nic Hartley May 20 '17 at 0:31
  • \$\begingroup\$ @QPaysTaxes How is review different from here's how I would do that? I think the only essential difference is that in review you also say why you would do things your way. Which I've said. It's more declarative and hence easy to understand. \$\endgroup\$ – user1685095 May 20 '17 at 0:37
  • 1
    \$\begingroup\$ Maybe it's obvious to you, but the reader perhaps never knew about itertools - the information you provide in this comment thread to defend your answer could go a long way towards improving your post. Alternative solutions are indeed not quite reviews, but they can be perfectly fine answers if it's more than just a code dump: describe your solution - perhaps the reader never knew about itertools, a mere sentence to point it out and tell the OP how accumulate can solve this problem much more elegantly, could dramatically improve the answer. Feel free to edit anytime =) \$\endgroup\$ – Mathieu Guindon May 20 '17 at 2:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.