[Question]
  [
> 
> **NOTICE:** This challenge is now closed: I will no longer be updating the leaderboard and will not change the accepted answer. However, you are free to run the controller and update the leaderboard yourself, if you wish.
> 
> 
> 
## [Join the chat!](https://chat.stackexchange.com/rooms/81067/the-break-room)
## Introduction
Good evening, traders! You are all traders for the golfing company PPCG. Your task is to make as much money as possible.
## Challenge
Write a program that buys and sells shares on the Stack Exchange Stock Exchange with the aim of making as much money as possible.
## Gameplay
All players will start with 5 shares and $100 in their bank. The game always starts with a share price of $10.
Each game will have 1000 rounds where the first round is round `1`. In each round, your program will be supplied four arguments as input: the current share price, the number of shares you hold, the amount of money you own and the round number (1-indexed). 
For example, if my program is `test1.py`, the share price is `100`, the number of shares I hold is `3`, the amount of money I have is `1200`, and the round number is `576`, my program will be run like so:
```
python test1.py 100 3 1200 576
```
In a round, the share price given to each player will be the same. This doesn't change until the end of the round.
In response, the player must print their command. There are two options:
* Buy shares: This command is given as `bn` where `n` is the number of shares you wish to buy. For example, if you want to buy 100 shares, you would output:
```
b100
```
When buying shares, you are allowed an overdraft of up to $1000. If you try to buy enough shares that exceed this overdraft (your bank balance goes below $-1000), you will be declared bankrupt. This means that you will lose all of your shares and your balance will be set to $50.
The share price will be unaffected by your command if you go bankrupt.
(If your balance is $-1000, you are not bankrupt. However if your balance is $-1001, you are bankrupt)
* Sell shares: This command is given as `sn` where `n` is the number of shares you wish to sell. For example, if you want to sell 100 shares, you would output:
```
s100
```
You may not sell more shares than you own. If you try to do this, your request will be denied, and you will skip the round.
If you want to skip the round and do nothing, output either `b0` or `s0`.
Your request will be denied if you try to buy or sell a negative number of shares and/or a non-integer number of shares.
After 5 rounds, at the end of each round, all players will be payed a dividend, the value of which is 5% of the mean average share price of the last 5 rounds.
## How does it work?
Initially the share price will be $10. At the end of each round, it will be recalculated using the formula:
$$\text{New Share Price} = \text{Old Share Price} + (\text{Number of shares bought}-\text{Number of shares sold})$$
The share price will be limited so that it never falls below $1.
To prevent overly rapid change, the change in share price is limited to a maximum of \$\pm$200\$.
## Rules
* Your program must have a name
  
* Your program is allowed a single text file for data storage. It must be stored in the same folder as your program
  
* Include in your answer details of how to run your program
  
* This KotH is open to all programming languages that are free-to-use and can be run on Windows 10
  
* Your score is based solely on the contents of your balance. Any money locked up in shares will not be counted
  
* You may edit your program at any time. Before each game, the latest code will be saved and compiled
  
* You should not write code which specifically targets another bot.
## Controller
The controller is written in Python and can be found here: <https://gist.github.com/beta-decay/a6abe40fc9f4ff6cac443395377ec31f>
At the end it will print a leaderboard and display a graph of how the share price changed throughout the game. 
For example, when two random bots were playing
![](https://i.stack.imgur.com/irSp0.png)
## Winning
The player with the highest amount of money in their balance at the end of the last game wins.
## Leaderboard
**Game 4: 16:14 10/08/2018**
```
Name                                Balance
Experienced Greedy Idiot            $14802860126910608746226775271608441476740220190868405578697473058787503167301288688412912141064764060957801420415934984247914753474481204843420999117641289792179203440895025689047561483400211597324662824868794009792985857917296068788434607950379253177065699908166901854516163240207641611196996217004494096517064741782361827125867827455285639964058498121173062045074772914323311612234964464095317202678432969866099864014974786854889944224928268964434751475446606732939913688961295787813863551384458839364617299883106342420461998689419913505735314365685264187374513996061826694192786379011458348988554845036604940421113739997490412464158065355335378462589602228039730
Equalizer                           $763185511031294813246284506179317396432985772155750823910419030867990447973211564091988995290789610193513321528772412563772470011147066425321453744308521967943712734185479563642323459564466177543928912648398244481744861744565800383179966018254551412512770699653538211331184147038781605464336206279313836606330
Percentage Trader                   $448397954167281544772103458977846133762031629256561243713673243996259286459758487106045850187688160858986472490834559645508673466589151486119551222357206708156491069820990603783876340193236064700332082781080188011584263709364962735827741094223755467455209136453381715027369221484319039100339776026752813930
OYAIB                               $8935960891618546760585096898089377896156886097652629690033599419878768424984255852521421137695754769495085398921618469764914237729576710889307470954692315601571866328742408488796145771039574397444873926883379666840494456194839899502761180282430561362538663182006432392949099112239702124912922930
Chimps on a Typewriter              $176504338999287847159247017725770908273849738720252130115528568718490320252556133502528055177870
Greedy B*****d                      $17689013777381240
Illiterate Dividend Investor        $2367418699671980
Lucky Number 6                      $4382725536910
Lone Accountant                     $90954970320
Buy/Reinvest                        $127330
Technical Analysis Robot            $126930
Dollar Cost Averager                $106130
Fibonacci                           $69930
Novice Broker                       $28130
Buy Low                             $6130
Naive Statistician                  $6130
Fallacious Gambler                  $6130
Passive Trader                      $4980
Half More or Nothing                $4920
Monkeys on a Typewriter             $66
```
[**View graphs of each contestant**](https://i.stack.imgur.com/BMe4F.png)
---
**[Related](https://codegolf.stackexchange.com/questions/91566/stock-exchange-koth) but the gameplay and winning criterion are very different to this challenge.**
  
[Answer]
# Chimps On A Typewriter
```
import random
from sys import argv
share_price = int(argv[1])
share_count = int(argv[2])
balance = float(argv[3])
x = random.random()
if x < 0.5:
    max_buy = balance / share_price
    buy_count = int(max_buy * random.random())
    print('b' + str(buy_count))
else:
    sell_count = int(share_count * random.random())
    print('s' + str(sell_count))
```
Chimps are smarter than monkeys, they won't buy stocks they can't afford, or sell stocks they don't have.
Still pretty random otherwise though.
Run with python3, but should(?) work with python2 as well
[Answer]
# The Experienced Greedy Idiot
PHP, tested on PHP >= 7, should work on previous ones as well.
```
<?php
class StickExchange
{
    private $dbFile;
    private $sharePrice;
    private $shares;
    private $balance;
    private $overdraft;
    public function __construct($sharePrice, $shares, $balance, $round)
    {
        $this->dbFile = __FILE__ . '.txt';
        $this->sharePrice = gmp_init($sharePrice);
        $this->shares = gmp_init($shares);
        $this->balance = gmp_init($this->parseScientificNotationToInt($balance));
        $this->overdraft = gmp_init(1000);
        $action = 'b';
        if ($round == 1) {
            $this->buy();
        } elseif ($round == 1000) {
            $this->sell();
        } else {
            $content = $this->getDbContent();
            $lastPrice = gmp_init($content['price']);
            $secondLastPrice = gmp_init($content['last_price']);
            $lastAction = $content['action'];
            $shareAndLastCmp = gmp_cmp($this->sharePrice, $lastPrice);
            $lastAndSecondLastCmp = gmp_cmp($lastPrice, $secondLastPrice);
            if ($shareAndLastCmp > 0 && $lastAndSecondLastCmp > 0) {
                if ($lastAction == 'b') {
                    $this->sell();
                    $action = 's';
                } else {
                    $this->buy();
                }
            } elseif ($shareAndLastCmp < 0 && $lastAndSecondLastCmp < 0) {
                if ($lastAction == 'b') {
                    $this->sell();
                    $action = 's';
                } else {
                    $this->skip();
                }
            } elseif ($shareAndLastCmp > 0) {
                $this->sell();
                $action = 's';
            } elseif ($shareAndLastCmp < 0) {
                $this->buy();
            } else {
                $this->skip();
            }
        }
        $this->setDbContent([
            'action' => $action,
            'price' => gmp_strval($this->sharePrice),
            'last_price' => isset($lastPrice) ? gmp_strval($lastPrice) : '0',
        ]);
    }
    private function parseScientificNotationToInt($number)
    {
        if (strpos($number, 'e+') !== false) {
            $sParts = explode('e', $number);
            $parts = explode('.', $sParts[0]);
            $exp = (int)$sParts[1];
            if (count($parts) > 1) {
                $number = $parts[0] . $parts[1];
                $exp -= strlen($parts[1]);
            } else {
                $number = $parts[0];
            }
            $number = gmp_init($number);
            $pow = gmp_pow(gmp_init(10), $exp);
            return gmp_strval(gmp_mul($number, $pow));
        } elseif (strpos($number, 'e-') !== false) {
            return sprintf('%d', $number);
        } else {
            $parts = explode('.', $number);
            return $parts[0];
        }
    }
    private function getDbContent()
    {
        return unserialize(file_get_contents($this->dbFile));
    }
    private function setDbContent($content)
    {
        file_put_contents($this->dbFile, serialize($content));
    }
    private function buy()
    {
        $realBalance = gmp_add($this->balance, $this->overdraft);
        $sharesToBuy = gmp_div($realBalance, $this->sharePrice);
        $this->stdout('b' . gmp_strval($sharesToBuy));
    }
    private function sell()
    {
        $this->stdout('s' . gmp_strval($this->shares));
    }
    private function skip()
    {
        $this->stdout('b0');
    }
    private function stdout($string)
    {
        $stdout = fopen('php://stdout', 'w');
        fputs($stdout, $string);
        fclose($stdout);
    }
}
new StickExchange($argv[1], $argv[2], $argv[3], $argv[4]);
```
An updated version of "The Greedy Idiot" with re-structured behavior and bug fixes related to working with huge numbers.
### Notes:
* Save in a file and run it like this: `php C:\path\path\stack_exchange.php 10 5 100 1`
* This script creates a text file with same name as the script file and a `.txt` appended to the end. So please run with an user with appropriate write permission on the script path.
* A simple how to install PHP 7.2 on windows: <http://www.dorusomcutean.com/how-to-install-php-7-2-on-windows/>
* To work with super huge numbers, I had to use [GMP](http://php.net/manual/en/book.gmp.php), so these two lines on `php.ini` should be un-commented (the semi-colon at start of line should be removed, if it isn't already):
	+ `; extension_dir = "ext"`
	+ `;extension=gmp`
[Answer]
# OYAIB
```
from sys import argv
share_price = float(argv[1])
shares      = int(argv[2])
cash        = float(argv[3])
cur_round   = int(argv[4])
tot_rounds  = 1000.0
investments = shares * share_price
total_assets = investments + cash
target_cash = round(cur_round / tot_rounds * total_assets)
if target_cash > cash:
  shares_to_sell = min(shares, round((target_cash - cash) / share_price))
  print('s%d' % shares_to_sell)
else:
  shares_to_buy = round((cash - target_cash) / share_price)
  print('b%d' % shares_to_buy)
```
Following the old saying of "own your age in bonds," this program tries to do the same. This way we aren't subject to market volatility at the end-game.
**Edit:** Looking at the controller it shows that we can only buy/sell full shares, but can have a fractional account balance.
[Answer]
# Lone Accountant
`buy-sell.py`:
```
from sys import argv
Price = int(argv[1])
Shares = int(argv[2])
Balance = float(argv[3])
Round = int(argv[4])
if Round % 2 == 0: print('s' + str(Shares))
if Round % 2 == 1: print('b' + str(int((Balance + 1000) / Price)))
```
Doesn't store anything in `buy-sell.txt`.
In odd rounds, it buys as many shares as it can. In even rounds, it sells all of its shares.
The intent is to first raise the share price by buying as many shares as possible, and then sell those shares to get more money. It works because the final round is even (round 1000).
Even though the share price will remain the same (`5`) after each pair of rounds (assuming the bot is alone, therefore ***Lone* Accountant**), the bot's balance increases, since the selling price is higher than the buying price, and more balance leads to the ability of buying more shares. It's a vicious cycle, but in a good way (for me).
The major vulnerability comes with evil bots playing alongside, selling in order to lower the share price (not sure if it's good for them either). In this case, the bot may remain with a balance of $-890, provided there are enough evil bots. This accountant really wants their peace of mind. ;-)
[Answer]
# The Passive Trader
```
from sys import argv
share_price = int(argv[1])
balance = float(argv[3])
round_num = int(argv[4])
if round_num == 1:
    print('b%s' % str(int(balance / share_price)))
else:
    print('b0')
```
This guy isn't big on this whole "Stocks" thing, but he heard that if he just spends a little money now, he'll get little bits of money over time that'll add up to more than he spent.
He'll buy enough stocks to go to $0 (no overdraft for this fella, he's not gunna put himself in debt for a little profit), then sit around letting the dividends build
Run with python3, but should(?) work with python2 as well.
[Answer]
# The Naïve Statistician
Made for Python 3, might work in Python 2
```
from sys import argv
from math import floor
# Save an entry to the stock history
def save_history(price):
    with open('stockhistory.txt', 'a') as f:
        f.write(str(price) + '\n')
# Load the stock history
def load_history():
    with open('stockhistory.txt', 'r') as f:
        return [float(line.strip()) for line in f]
# Calculate average price rise/fall streak length
def average_streak(history, condition):
    streaks = []
    current_streak = 0
    last_price = history[0]
    for price in history[1:]:
        if condition(last_price, price):
            current_streak += 1
        elif current_streak:
            streaks += [current_streak]
            current_streak = 0
        last_price = price
    if current_streak:
        streaks += [current_streak]
    return sum(streaks) / len(streaks) if streaks else None
# Calculate the current streak length
def current_streak(history, condition):
    streak = 0
    while streak < len(history) - 1 and condition(history[-streak - 2], history[-streak - 1]):
        streak += 1
    return streak
def run(share_price, share_count, balance, round_number):
    save_history(share_price)
    # Sell all shares if it is the last round
    if round_number == 1000:
        print('s' + str(int(share_count)))
        return
    # Buy as many shares as possible if the price is down to one, as there's
    # nothing to lose
    if share_price == 1:
        buy_count = int(balance + 1000)
        print('b' + str(buy_count))
        return
    history = load_history()
    # Calculate the average and current rise/fall streaks
    average_rise = average_streak(history, lambda a, b: a <= b)
    current_rise = current_streak(history, lambda a, b: a <= b)
    average_fall = average_streak(history, lambda a, b: a >= b)
    current_fall = current_streak(history, lambda a, b: a >= b)
    # Do nothing if there's no analyzed data
    if not average_fall or not average_rise:
        print('b0')
        return
    # Buy shares if the current rise streak is as long as or longer than average
    if current_rise > current_fall and current_rise >= average_rise:
        buy_count = (balance + 1000) / share_price
        print('b' + str(int(buy_count)))
        return
    # Sell shares if the current fall streak is as long as or longer than average
    if current_fall > current_rise and current_fall >= average_fall:
        print('s' + str(int(share_count)))
        return
    # Otherwise, do nothing    
    print('b0')
run(*map(float, argv[1:]))
```
This is a naïve statistician that tries to predict stock prices by only buying/selling if the price has risen/fallen for longer than usual, while also buying stocks if the price is down to one and selling all stocks on the last round.
[Answer]
# Percentage Trader Python3
(maybe works in python2)
```
import sys
args=sys.argv
price=int(args[1])
held=int(args[2])
money=int(args[3])
roundNum=int(args[4])
prevPrice=0
if roundNum==1:
    print("b"+str((money+1000)//price))
else:
    if roundNum==1000:
        print("s"+str(held))
    else:
        with open("percentageTrader.dat","r") as f:
            prevPrice=int(f.read())
        if(price>prevPrice):
            toSell=int(held*int(1000000*(price-prevPrice))/(price))//1000000
            print("s"+str(toSell))
        if(price<prevPrice):
            toBuy=int(((money+1000)//price)*int(1000000*(prevPrice-price))//(prevPrice))//1000000
            print("b"+str(toBuy))
        if(price==prevPrice):
            print("b0")
with open("percentageTrader.dat","w") as f:
    f.write(str(price))
```
### Instructions on running
* Save as filename.py
* Run with python filename.py price #shares balance round#
### How it works
* First round the bot purchases as many shares as it can afford.
* If the price increases, the bot sells a percentage of shares equal to the percentage increase in price(calculated from new value)
* If the price decreases, the bot buys a percentage of the maximum shares it could buy equal to the percentage decrease in price(calculated from previous value)
* Sells off everything at round 1000
Changes should hopefully remove the problems caused by floating point division
[Answer]
# Equalizer
```
from sys import argv
p, n, b, r = map(int, argv[1:])
c = p*n
print "bs"[(c+b)/2>b] + str(int(abs(((c-b)/2)/p))) if r < 999.5 else "s" + str(int(n))
```
Partitions its financial resources equally between cash and stocks on every round except the last. I believe this strategy to be a mathematically sound way of making at least *some* money, but I may be proven wrong.
There may or not be bugs that I haven't caught. Also golfed somewhat.
[Answer]
# Monkeys On A Typewriter
```
import random
cmd = ['b', 's'][int(random.random() * 2)]
num = str(int(random.random() * 1000000))
print("%s%s" % (cmd, num))
```
It's a bunch of monkeys on typewriters.
Randomly sells or buys X stocks, where:  
`0 <= X <= 1,000,000`
Run with python3, but should(?) work with python2 as well
[Answer]
# Buy Low
(Python 2 or 3)
```
import random
def run(price, shares, balance, round_):
    # We get no value from our leftover shares at the end, so sell them all.
    if round_ == 1000:
        print('s' + str(int(shares)))
        return
    # If the price is low enough, buy everything we can.
    if price <= 20 + round_ * 60:
        print('b' + str((balance + 1000) // price))
        return
    # If we have no shares, wait for the price to drop.
    if shares == 0:
        print('b0')
        return
    # Sometimes sell shares so we can buy if the price gets low again.
    if random.random() < 0.4:
        print('s1')
        return
    # Otherwise, just wait for a better price.
    print('b0')
if __name__ == '__main__':
    import sys
    run(*[float(x) for x in sys.argv[1:]])
```
[Answer]
# Fallacious Gambler
(Python 2 or 3)
```
import random
def run(price, shares, balance, round_):
    # We get no value from our leftover shares at the end, so sell them all.
    if round_ == 1000:
        print('s' + str(int(shares)))
        return
    # For the first round, just watch.
    if round_ == 1:
        with open('fg.txt', 'w') as f:
            f.write('1 0 10')
        print('b0')
        return
    # Get the state.
    with open('fg.txt') as f:
        direction, streak, previous = map(int, f.read().strip().split())
    change = price - previous
    # If the market isn't moving, wait for it to get hot again.
    if change == 0:
        print('b0')
        return
    # Keep track of the market direction.
    if (change > 0) == (direction > 0):
        streak += 1
    else:
        streak = 0
        direction *= -1
    # If the market's been going one way for too long, it has to switch, right?
    if streak > 5:
        if direction > 0:
            print('s' + str(shares // 2))
        else:
            print('b' + str((balance + 1000) // price // 2))
    # Otherwise, the market's too volatile.
    else:
        print('b0')
    # Save the state.
    with open('fg.txt', 'w') as f:
        f.write('%d %d %d' % (direction, streak, price))
if __name__ == '__main__':
    import sys
    run(*[float(x) for x in sys.argv[1:]])
```
[Answer]
# The Dollar Cost Averager
(tested with Python 3.7)
First post in codegolf so tell me if I did something wrong.
The basic idea is to buy one share each round if that's possible and sell all shares at the end. 
```
from sys import argv
share_price = int(argv[1])
share_count = int(argv[2])
balance = float(argv[3])
round = int(argv[4])
if round < 1000:
    if balance > share_price-1000:
        print("b1")
    else:
        print("b0")
else:
    print("s" + str(share_count))
```
[Answer]
# The (Dyalog) APL Farmer
```
r←apl_stock_farmer args
 round←¯1↑args
 :If 1=round
     (buyPrice sellPrice)←10 0
     bought←1
     (currPrice shares balance)←3↑args
     r←'b10'
 :ElseIf 1000=round
     r←'s',⍕shares
 :Else
     (currPrice shares balance)←3↑args
     :If (currPrice>buyPrice)∧bought
         bought←0
         sellPrice←currPrice
         r←'s',⍕shares
     :ElseIf (currPrice<sellPrice)∧~bought
         bought←1
         buyPrice←currPrice
         r←'b',⍕⌊(1000+balance)÷currPrice
     :Else
         r←'b0'
     :End
 :End
```
A TradFn which buys every possible share on the first round, and only sells when the current price of the shares is higher than the price they were bought for. After selling, the bot will only buy shares that are cheaper than the price it last sold shares for.
That's because the farmer's accountant told him that's how you do stock trading. "Buy low, sell high" and all that stuff.
### Disclaimer
This is my first attempt at a KotH challenge, and since I basically only do APL here, I decided to go on with it.
That said, I'm not completely sure if this will be able to be run alongside the other bots, since it's a Tradfn and can't be fed directly into a CMD/Bash shell.
So, to run this in Bash, you need the following command:
`$ echo apl_stock_farmer args | dyalog 'stock_exchange.dws' -script`
Where:
`apl_stock_farmer` is the name of the function, which is in the first line of code.
`args` is a vector of space separated arguments (in the first round, it would be `10 5 100 1`).
`dyalog` is the path to the Dyalog executable
`'stock_exchange.dws'` is the name (or path, if the file is not in the same directory the shell has open) of the workspace that contains the function. That workspace file can be obtained by opening a clear workspace, typing `)ed apl_stock_farmer`, pasting the code above and then doing a `)save <path>`. I can also provide this workspace file if that would be easier.
`-script` is just an argument that makes dyalog execute the given code and print to stdout without actually opening the REPL.
Unfortunately, I haven't found a way to make it work with the Windows CMD or Powershell, so I ran it using Git Bash.
I'm not sure how feasible it is to put this bot on the competition, but I like this code way too much not to post it.
[Answer]
# Illiterate Dividend Investor
```
import random
from sys import argv
price = float(argv[1])
shares = int(argv[2])
cash = float(argv[3])
round = int(argv[4])
# buy 1st round, sell last round
if round == 1:
    print('b' + str(int((cash + 1000) / price)))
elif round == 1000:
    print('s' + str(shares))
# round right before dividend: sell
elif round % 5 == 4:
    print('s' + str(shares))
# 1 round after dividend: buy
elif round % 5 == 0:
    print('b' + str(int((cash + 1000) / price)))
# 2 rounds after dividend: 50/50 sell/try to buy
elif round % 5 == 1:
    if random.random() < 0.5:
        print('s' + str(shares))
    else:
        print('b' + str(int((cash + 1000) / price)))
# 3 rounds after dividend: sell if own shares (didn't sell last round), else buy
elif round % 5 == 2:
    if shares > 0:
        print('s' + str(shares))
    else:
        print('b' + str(int((cash + 1000) / price)))
# otherwise, 4 rounds after dividend, buy
else:
    print('b' + str(int((cash + 1000) / price)))
```
Assumes after dividends, people have more cash, so they will be more likely to buy. Sells right before dividends, buys right after. Goes through one other sell/buy cycle in the other 3 rounds.
[Answer]
# Novice Broker (but gets the basic idea)
`se_stock_exchange.rb`:
```
DATA_FILE = $0.sub /\.rb$/, ".data"
NUM_ROUNDS = 1000
share_price, num_shares, money, round = ARGV.map &:to_i
order = "s0"
if round == NUM_ROUNDS
  puts "s#{num_shares}"
  exit
end
if File.exists? DATA_FILE
  last_price, trend, bought_price = File.read(DATA_FILE).lines.map &:to_i
else
  last_price = 0
  trend = -1
  bought_price = 0
end
if (new_trend = share_price <=> last_price) != trend
  case trend
  when -1
    order = "b#{(money + 1000) / share_price}"
    bought_price = [bought_price, share_price].max
  when 1
    if share_price > bought_price
      order = "s#{num_shares}"
      bought_price = 0
    end
  end
  trend = new_trend
end
File.open(DATA_FILE, "w") { |f| f.puts share_price, trend, bought_price }
puts order
```
Waits until the price turns around, then buys/sells everything. I mean, that's what it says to do in *Day Trading for Dummies* Note: this is probably a real book, and that's probably something someone might get from it.
Saves data in `se_stock_exchange.data`. Run with `ruby se_stock_exchange.rb ${SHARE_PRICE} ${SHARES} ${MONEY} ${ROUND}` (substituting the appropriate values).
[Answer]
# Half More or Nothing
```
def run(price, shares, balance, cur_round):
    if cur_round==1000:
        print('s'+str(int(shares)))
        return
    
    if cur_round==1:
        with open('HalfMoreOrNothing.dat', 'w') as f:
            f.write(str(int(price)))
        print('b'+str(int((balance+1000)/price)))
        return
    
    if shares==0:
        with open('HalfMoreOrNothing.dat', 'w') as f:
            f.write(str(int(price)))
        print('b'+str(int((balance+1000)/price)))
        return
    
    with open('HalfMoreOrNothing.dat', 'r') as f:
        bought_price=int(f.read())
    if price>=bought_price*1.5:
        print('s'+str(int(shares)))
        return
    
    print('b0')
if __name__ == '__main__':
    import sys
    run(*[float(x) for x in sys.argv[1:]])
```
I rarely use Python, let me know if this generates an error somewhere.
The strategy is to wait until the share price is at least 50% bigger than the price at the moment of bying them, then sell them, then immediately buy new shares so it can wait for the new share price raise.
Hopefully, ~~people~~ chimps won't start to sell shares near the end... (it seems that most bots just wait for the right moment, whatever that is)
[Answer]
## Buy/Reinvest as much as possible!
Similar to my Dollar-Cost Averager that did, surprisingly, quite average, this buys each round as many shares as are affordable and only sells them in the last round.
```
from sys import argv
share_price = int(argv[1])
share_count = int(argv[2])
balance = float(argv[3])
round = int(argv[4])
if round < 1000:
    if balance > share_price-1000:
        buy_count = int((balance+1000)/share_price)
        print("b"+str(buy_count))
    else:
        print("b0")
else:
    print("s" + str(share_count))
```
[Answer]
# Fibonacci
I've rewritten this in Python 3 to make things easier. Hopefully!
```
import math
from sys import argv
price = float(argv[1])
shares = int(argv[2])
balance = float(argv[3])
roundNum = int(argv[4])
fibonacci = [2,3,5,8,13,21,34,55,89,144,233,377,610,987]
if (roundNum == 1):
    buy = int((balance+1000)/price)
    print('b' + str(buy))
elif (roundNum in fibonacci) and roundNum % 2 == 1 and balance > 0:
    buy = int((balance/price)/2)
    print('b' + str(buy))
elif ((roundNum in fibonacci) and roundNum % 2 == 0) or roundNum % 100 == 0:
    if (roundNum == 1000):
        sell = shares
        print('s' + str(sell))
    else:
        sell = math.ceil(shares/2)
        print('s' + str(sell))
else:
    print('b0')
```
It buys half the maximum amount of shares that is affordable when the round is equal to an odd Fibonacci number and sells half of the available shares when the round is equal to an even Fibonacci number and also every 100 rounds. Sells all shares on round 1000. Otherwise, it just waits. Only buys shares when balance is positive.
[Answer]
## Technical Analysis Robot
I study business economics so I tried to realize the simpliest method for analizing a stock market (the technical analysis). According to the theory you just have to analyze all the minimums of the graph to see if there is a trend (up ord down). During an up trend you have to buy and during a down trend you have to sell.
I don't think that this method will work too well but let's give it a try :)
```
import sys
from sys import argv
share_price = int(argv[1])
share_number = int(argv[2])
bank_account = float(argv[3])
round_number = int(argv[4])
max_buy_greedily = (1000 + bank_account) / share_price
minima = []
def log():
    f = open("log_technical_analysis.txt","a+")
    f.write("%d;" % share_price)
def analyze():
    f = open("log_technical_analysis.txt","r+")
    line = f.readline()
    values = line.split(";")
    values.pop()
    for i in range(len(values) - 1):
        if i > 0 and int(values[i-1]) > int(values[i]) and int(values[i+1]) > int(values[i]):
            minima.append(int(values[i]))
    if len(minima) >= 3 and minima[len(minima) - 1] > minima[len(minima) - 2] and minima[len(minima) - 2] > minima[len(minima) - 3]:
        print('b' + str(int(max_buy_greedily)))
    elif len(minima) >= 3 and minima[len(minima) - 1] < minima[len(minima) - 2] and minima[len(minima) - 2] < minima[len(minima) - 3]:
        print('s' + str(share_number))
    else:
        print('b0')
if round_number >= 994:
    print('s' + str(share_number))
    sys.exit(0)
if share_price <= 15:
    print('b' + str(int(max_buy_greedily)))
    log()
    sys.exit(0)
log()
analyze()
sys.exit(0)
```
Tested with python3
[Answer]
**Greedy B\*\*\*\*\*d**
```
# Gready one...
from sys import argv
SMA_PERIOD = 5
LAST_BUY_DAY = 985
LAST_SELL_DAY = 993
# Save an entry to the stock history
def save_history(price):
    with open('db.txt', 'a') as f:
        f.write(str(price) + '\n')
# Load the stock history
def load_history():
    with open('db.txt', 'r') as f:
        return [float(line.strip()) for line in f]
def get_sma(d, n):
    l = d[-n:]
    return int(sum(l) / len(l))
def buy(price, account):
    if account + 1000 > 0:
        print 'b' + str(int((account + 1000) / price))
        return
    print 'b0'
def sell(holdings):
    print 's'+ str(int(holdings))
def run(price, holdings, account, day):
    save_history(price)
    d = load_history()
    if price <= get_sma(d, SMA_PERIOD) and day < LAST_BUY_DAY:
        return buy(price, account)
    if price > get_sma(d, SMA_PERIOD):
        return sell(holdings)
    if day >= LAST_SELL_DAY:
        return sell(holdings)
    # Otherwise, do nothing    
    print 'b0'
run(*map(float, argv[1:]))  
```
He will go all in when its cheap and sell it all once the price goes up...
[Answer]
## Lucky Number 6
EDIT: Oh ffs, I think me not converting the selling count to int was one of my problems, well here we go again.
Probably my last contribution, unless I'm bored at work and make something a bit more sophisticated, but I fell like the sophisticated bots already fill the niches.
This guy basically sells some of his shares every 6 rounds, because hey 6 is his lucky number.
```
from sys import argv
import random
share_price = int(argv[1])
share_count = int(argv[2])
balance = float(argv[3])
round = int(argv[4])
x = random.uniform(1,2)
if round == 1 or round == 1000:
    print("s"+str(share_count))
elif round % 6 == 0 and share_price >= 10:
    sell = int(share_count/x)
    print("s"+str(sell))
elif balance > share_price-1000:
    buy_count = int((balance+1000)/share_price)
    print("b"+str(buy_count))
else:
    print("b0")
```
]