Stack Exchange Stock Exchange ~ Revised

35

11

Background

You are all traders for a slightly less than reputable stock firm. You all are part of a group of traders who focus only on one specific stock.

Each hour each trader has a chance to Buy X stocks or Sell X stocks. There are 50 hours per round and 3 rounds per competition. At the end of all of the rounds the trader with the highest average value wins a trip to Jamaica!

Gameplay

There are 3 rounds of 50 turns each.

Each trader begins the round with $5000 and A random number of shares between 20 and 30 shares. The price of the shares starts at a random number between 10 and 150.

Each turn each trader can Buy any number of shares they can afford or Sell any number of shares they currently hold, each for the current price per share.

The price per share increases by a random number between 1 and 5 for each share bought and decreases by a random value between 2 and 6 for each share sold. The minimum price is $1.

It is important to note that all traders process their transactions at the same time, meaning that any trader buying/selling shares will not affect the price until the next turn.

The player with the highest average value at the end of the 3 rounds wins. Value is determined by taking the amount of money left over at the end of the round and adding the number of shares owned by the trader * closing market price.

Arguments

Your program will be rerun at the start of each turn receiving the current market price, the trader's current amount of money and the number of shares owned by that trader.

Ex:

120 5000 0

Output

Your trader program must output a letter corresponding to the action it would like to take followed by the quantity.

Ex:

B10 //Buy 10 shares

or

S3 //Sell 3 shares

The trader also has the option to not do anything that turn. That can be accomplished by outputting a W or any other command that is not 'B>amnt<' or 'S>amnt<'

Submissions

Your program will be inside a 'players/>your program name<' directory:

+-- players
|   +-- BotNameFolder
|       +-- BotProgram   

Please provide your code along with a command line argument to run it from inside the 'players' directory. For example the Test1 trader could be run with java -cp "Test1" Test1

Additional Rules

Go ahead, shoot yourself EmoWolf, Idc.

No messing with anything outside of your BotNameFolder directory, feel free to create files in there though for persistent info throughout rounds / turns.

Do not intentionally create programs to crash the simulation.

I will accept multiple entries per user, as long as the entries act as seperate entities (No insider trading).

Leaderboard

[java&-cp&"TestPlayer"&Test1]:$10027395221
[python&daydreamer/daydreamer.py]:$5000
[java&-cp&"DayTrader"&DayTrader]:$4713199930331196453

I will try to update the leaderboard at least once a day

Controller

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.math.BigInteger;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.Random;


public class Controller {

    public static BigInteger marketValue = BigInteger.valueOf(100);
    public static BigInteger newValue = BigInteger.valueOf(100);

    public static final char BUY = 'B';
    public static final char SELL = 'S';

    public static final int MARKET_INDEX = 1;
    public static final int MONEY_INDEX = 2;
    public static final int SHARE_INDEX = 3;

    public static int numRunning = 0;
    public static final int MAX_RUNNING = 10;

    public static void main(String[] args){
        try {
            BufferedReader br1 = new BufferedReader(new InputStreamReader(new FileInputStream("resources/config")));

            int numRounds = Integer.parseInt(br1.readLine());
            int turnsPerRound = Integer.parseInt(br1.readLine());

            //Create the array of players
            List<String> players = new LinkedList<String>();
            String line1 = null;
            while((line1 = br1.readLine()) != null){
                players.add(line1);
            }
            BigInteger[] totalVals = new BigInteger[players.size()];
            for(int i = 0; i < totalVals.length; i++){
                totalVals[i] = BigInteger.valueOf(0);
            }
            br1.close();

            //Begin processing
            for(int round = 0; round < numRounds; round++){
                //Create players' shares and currency array
                Map<String,BigInteger[]> vals = new HashMap<String, BigInteger[]>();
                for(int i = 0; i < players.size(); i++){
                    vals.put(players.get(i), new BigInteger[]{BigInteger.valueOf(5000), BigInteger.valueOf(getRandInt(20,30))});
                }
                marketValue = BigInteger.valueOf(getRandInt(10,150));
                newValue = marketValue;
                for(int turn = 0; turn < turnsPerRound; turn++){
                    marketValue = newValue;
                    Queue<Object[]> processQueue = new LinkedList<Object[]>();
                    for(String playerKey : vals.keySet()){
                        BigInteger[] valSet = vals.get(playerKey);
                        String[] pkParts = playerKey.split("&");
                        String[] parts = new String[pkParts.length + 3];
                        for(int i = 0; i < pkParts.length; i++){
                            parts[i] = pkParts[i];
                        }
                        parts[pkParts.length] = marketValue + "";
                        parts[pkParts.length + 1] = valSet[0] + "";
                        parts[pkParts.length + 2] = valSet[1] + "";
                        processQueue.add(new Object[]{playerKey, parts});
                    }

                    while(!processQueue.isEmpty() || numRunning > 0){
                        if(numRunning < MAX_RUNNING && !processQueue.isEmpty()){
                            numRunning++;
                            Object[] o = processQueue.poll();
                            String pKey = (String)(o[0]);
                            String[] p = (String[])(o[1]);
                            try {
                                Process proc = new ProcessBuilder(p).directory(new File("resources/players").getAbsoluteFile()).start();
                                BufferedReader br = new BufferedReader(new InputStreamReader(proc.getInputStream()));
                                String line = br.readLine();
                                br.close();
                                switch(line.charAt(0)){
                                case BUY :
                                    BigInteger numShares = new BigInteger(line.substring(1).trim());
                                    if(numShares.multiply(marketValue).compareTo(vals.get(pKey)[0]) <= 0){
                                        BigInteger[] tempVals = vals.get(pKey);
                                        tempVals[0] = tempVals[0].subtract(numShares.multiply(marketValue));
                                        tempVals[1] = tempVals[1].add(numShares);
                                        vals.put(pKey, tempVals);
                                        newValue = newValue.add(numShares.multiply(BigInteger.valueOf(getRandInt(0,2))));
                                        if(newValue.compareTo(BigInteger.valueOf(Integer.MAX_VALUE)) >= 1){
                                            newValue = BigInteger.valueOf(Integer.MAX_VALUE - 1);
                                        }
                                    }
                                    break;
                                case SELL:
                                    BigInteger shares = new BigInteger(line.substring(1).trim());
                                    if(shares.compareTo(vals.get(pKey)[1]) <= 0){
                                        BigInteger[] tempVals = vals.get(pKey);
                                        tempVals[0] = tempVals[0].add(shares.multiply(marketValue));
                                        tempVals[1] = tempVals[1].subtract(shares);
                                        vals.put(pKey, tempVals);
                                        newValue = newValue.subtract(shares.multiply(BigInteger.valueOf(getRandInt(5,10))));
                                        if(newValue.compareTo(BigInteger.valueOf(1)) <= -1){
                                            newValue = BigInteger.valueOf(1);
                                        }
                                    }
                                    break;
                                }
                            } catch (Exception e) {
                                System.err.println("[" + pKey + "] threw error:");
                                e.printStackTrace();
                            } finally{
                                numRunning--;
                            }
                        }else{
                            try{
                                Thread.sleep(50);
                                continue;
                            }catch(InterruptedException e){
                                continue;
                            }
                        }
                    }
                    System.out.println("Turn " + turn + " over: " + marketValue);
                }
                System.out.println("End of round market value is: " + marketValue);
                int count = 0;
                for(String player : vals.keySet()){
                    totalVals[count] = totalVals[count].add(vals.get(player)[0].add(vals.get(player)[1].multiply(marketValue)));
                    count++;
                }
                newValue = BigInteger.valueOf(100);
            }
            for(int i = 0; i < players.size(); i++){
                System.out.println("[" + players.get(i) + "]:$" + (totalVals[i].divide(BigInteger.valueOf(numRounds))));
            }
        } catch (Exception e) {
            System.err.println("An exception occured while running the controller.");
            e.printStackTrace();
        }
    }
    public static Random r = new Random(new Date().getTime());
    public static int getRandInt(int min, int max){
        return r.nextInt(max - min) + min;
    }
}

Compile this with java Controller.java and run from a directory containing a directory like below:

+-- resources
|   +-- config
|   +-- players
|       +-- Player1Folder
|           +-- Player1Program
|       +-- Player2Folder
|           +-- Player2Program

The file config should look something like this:

3
50
java&-cp&"TestPlayer"&Test1
python&daydreamer/daydreamer.py
java&-cp&"DayTrader"&DayTrader

First number is number of rounds, second number is turns per round, followed by the commands to run each player.

Replace spaces with ampersands! ('&')

~Let me know if I can improve the wording of this post at all, and happy trading!

spocot

Posted 2014-08-20T15:35:56.150

Reputation: 606

Question was closed 2015-08-23T14:45:34.840

1I've voted to close since despite attempts to rewrite the controller it appears there is still no way to judge the answers, and there is no meaningful leaderboard. – trichoplax – 2015-08-23T12:20:48.293

4It seems that the long-term trend in a busy market will see the share have a negative value. – Peter Taylor – 2014-08-20T15:47:14.037

Price cannot go below 1. Forgot to mention that. – spocot – 2014-08-20T15:47:53.087

I'm not so sure prices will fall. Players can only buy, not sell, in the first round, right? – xnor – 2014-08-20T16:07:12.107

@xnor you can only sell shares if you own them, the controller checks this, and since the round starts you with 0 shares, you don't have any to sell. If you try to sell more than what you own it is effectively the same as skipping the turn. – spocot – 2014-08-20T16:12:46.627

What happens if you buy more than you can afford? Your very own Test1 program, included in the challenge, does not check for this. It just blindly tries to buy 10 shares. – Rainbolt – 2014-08-20T16:24:42.277

@Rainbolt Controller does a check, and if you can't afford the number you requested, it doesn't sell you any and you effectively skip your turn. My test program is very rudamentary, it willingly skips its turn until it can buy 10 at a time. – spocot – 2014-08-20T16:25:45.277

2@xnor, every share bought increases the price by an average of 3, and every share sold decreases it by an average of 3.5. In the long term in a busy market, the total number of shares currently held will be less than 1/7 of the total number bought in the entire history. – Peter Taylor – 2014-08-20T16:38:59.317

What kind of OS will you be running this on? If it's Linux, can I create a system variable? – Beta Decay – 2014-08-20T16:52:36.513

@BetaDecay It will be running on a fresh Ubuntu VM, so yah go ahead :) – spocot – 2014-08-20T16:58:54.810

@spocot Ah, cheers! – Beta Decay – 2014-08-20T17:00:02.143

Hey, as part of the leaderboard, can you post the stock price? – Beta Decay – 2014-08-20T18:21:10.797

1You could make an accent pun and name this challenge "Stack Market". – cjfaure – 2014-08-20T18:21:57.157

6Could you put your controller program on something like Github and include a link so that we can test at home? – Peter Taylor – 2014-08-20T19:13:06.820

1Is there a way to indicate if it is the first move (or last move) so we could clear our storage? – Moop – 2014-08-20T19:41:40.207

$4713199930331196453 is a very large amount of money - is that an exponential growth rate? – isaacg – 2014-08-20T20:01:47.947

6Looking at the leaderboard, I think the game is currently flawed. E.g., start at $14/sh, buy 357 (own 357, $0 in bank). Choose random number (3). Price goes up by 3357 to $1085/sh. Next round. Sell all 357 shares (own 0, $387,345 in bank). Choose random number (3). Price goes down by 3357 to $14/sh. Next round. After two rounds, the price has not changed and your bank has increased 77x (similar but less dramatic results can be had with other starting random variables). I propose changing to for each transaction instead of for each share for more reasonable values. – None – 2014-08-20T20:28:03.993

agree with @tolos about the flaw. I propose that traders are given a number of shares to start with so that there isn't an inevitable share value increase after the first round. Otherwise, there is no way to disrupt traders using this strategy e.g. traders start with $5000 + 200 shares. – rdans – 2014-08-20T20:34:55.520

@Moop store the number 1 on disk and increment it on every turn. When the file doesn't exist (or the counter is on 151 if the file is still there from a previous run) its the first turn and when your counter gets to 150, its the last turn – rdans – 2014-08-20T20:57:55.670

@ryan I could imagine a bug or two could happen during the competition and then spocot would restart it and mess up the counting system. – Moop – 2014-08-20T21:01:58.867

@Moop (and to the OP) I would expect the text environment to be clean between trials. – Rainbolt – 2014-08-20T21:57:18.973

I suggest to aggressively increase the number of rounds from 3 to 1000000 (or so) to rule out random effects. – Bob Genom – 2014-08-20T21:59:13.667

1In my eyes the minimum price of $1 is a strategic game fault. Any (float) value between $1 and $0 (inclusive) should be allowed as well. Once $0 is touched the price should be trapped at $0 (no escape == crash). – Bob Genom – 2014-08-20T22:14:45.670

1Suggestion for game improvement: To more realistically simulate the market, and prevent the runaway effects we are seeing, I propose that the price be changed after each share, not at day end. Order would be determined by randomly selecting a trader from all traders still attempting to buy or sell, after each share is bought or sold. – isaacg – 2014-08-21T06:11:13.430

4Or just build a real order book. – o0'. – 2014-08-21T08:21:26.783

You should also support selling short, that way there is something to do in the first round besides buying. – durron597 – 2014-08-21T14:10:47.123

1The control program is made in Java. It creates a Process from a ProcessBuilder and passes in the data as args to your program. It then attaches a BufferedReader to the process in order to read the std output from the program. It checks the output to see if it matches 'S>amnt<' or 'B>amnt<'. If it does, it performs checks to make sure the operation is valid. If the operation is not valid or the trader's output does not match what it is looking for, it skips that trader's turn. – spocot – 2014-08-21T14:40:32.603

2@ Everyone

I am in the process of redoing the money system to make exponential growth and market corruption from one trader preventable. I will post the code on github asap. – spocot – 2014-08-21T14:41:49.023

Ok, added Controller program to post. If anyone wants to suggest a better way to calculate something let me know. – spocot – 2014-08-21T15:39:17.850

Traders now start with a random num of shares between 20 and 30 – spocot – 2014-08-21T15:40:35.053

3Why start with a random num of shares? – Averroes – 2014-08-22T06:50:09.287

Do the people who have already played a round start afresh or is it just the newcomers? – Beta Decay – 2014-08-22T07:17:17.027

1Notes: 1. People wanting to test under Linux will need to remove the double-quotes from the Java examples in the config file. 2. The market price changes aren't what's documented in the spec. 3. If Controller.getRandInt is intended to be able to return max then it's buggy. 4. MAX_RUNNING is pointless because there's no multi-threading. 5. The controller has no real error handling, so when TestPlayer starts dying because the stock price is too hard, the controller spams error messages to the console. – Peter Taylor – 2014-08-22T23:05:55.940

2And where's the new leaderboard? – Sean D – 2014-08-22T23:38:23.413

I've tidied up the code and done three runs.

– Peter Taylor – 2014-08-23T00:30:11.810

@PeterTaylor The amount of money people are earning seems amazingly high... – Beta Decay – 2014-08-23T08:16:00.547

@BetaDecay, the market is broken. It takes 4 turns for the share value to start bouncing between the two caps (1 and 2147483646). – Peter Taylor – 2014-08-23T08:36:40.527

I've created a chat to discuss how the market should be fixed

– Peter Taylor – 2014-08-23T08:49:20.870

When's the next run going to be? – Beta Decay – 2014-08-27T09:46:31.387

Answers

18

I present 'daydreamer', who is always asleep and forgets to buy or sell anything. He hopes that other players will have a net loss. Python code:

if __name__ == "__main__":
    print "W"

run with python daydreamer\daydreamer.py 120 5000 0 or whatever values you want.

I will post a more serious answer later, this is just to get the ball rolling :)

stokastic

Posted 2014-08-20T15:35:56.150

Reputation: 981

3I don't think that will run - you need to indent the print. – isaacg – 2014-08-20T16:50:08.267

6Given that the stock price will tend to drop in the long run, not trading may be an excellent strategy. – None – 2014-08-21T04:04:26.067

5A strange game: the only winning move is not to play. How about a nice game of chess? – Tim S. – 2014-08-22T14:29:26.417

13

DayTrader

Updated for rule change made on 8/21/2014, where players now start with 20-30 shares.

Buys as much as possible, then sells as much as possible.

Philosophy

We hope that the below pattern will repeat itself over and over. Note that by adhering to this pattern, we also contribute to it.

  • Everyone can only buy or hold on round one. The value can only increase, so we buy.
  • Everyone can buy more, hold, or sell on round two. We don't expect many players to buy on round two, so we sell.

The pattern is crystal clear at the beginning. Value will increase after round one. It should decrease after round two. Beyond that, projections get fuzzy. I expect to do well in the early rounds, before the market stabilizes.

import java.math.BigInteger;

/**
 * Submission for http://codegolf.stackexchange.com/q/36515/18487
 * @author Rainbolt
 */
public class DayTrader {

    /**
     * @param args the command line arguments containing the current 
     * market value, our current money, and our current shares
     */
    public static void main(String[] args) {
        BigInteger marketValue = new BigInteger(args[0]);
        BigInteger myMoney = new BigInteger(args[1]);
        BigInteger myShares = new BigInteger(args[2]);

        // If we have less than or equal to 30 shares, buy as much as possible
        if (myShares.compareTo(new BigInteger("30")) <= 0) {
            System.out.println("B" + myMoney.divide(marketValue).toString());
        // Otherwise, sell as much as possible
        } else {
            System.out.println("S" + myShares.toString());
        }
    }

}

Compile with javac DayTrader.java. Run with java -cp "DayTrader" DayTrader.

Rainbolt

Posted 2014-08-20T15:35:56.150

Reputation: 6 176

1Yay java! Makes it easier for me to run. – spocot – 2014-08-20T17:26:22.900

6Your bot made market extend beyond the max number for integers, so I implemented BigIntegers into the code. Since everyone's code used ints, it crashed pretty much everyone's bot cept for the daydreamer – spocot – 2014-08-20T18:04:21.163

@spocot I edited my implementation to use BigInteger. Hopefully that helps. – Rainbolt – 2014-08-20T18:26:49.023

I changed the max value for stocks to be the Integer max, but this still helps because the number of shares is technically limitless. – spocot – 2014-08-20T18:34:20.283

5I think this is an inherent problem in the rules. If one trader gets like 140 shares he could control the market by himself. In two rounds he can buy shares for 10 each and sell them for 140 each, leading to a win of 1300% (assuming nobody does the opposite). This will escalate to something like 5000 * 13^25, which is way to big. – Optokopper – 2014-08-20T18:50:28.580

2@spocot I just wanted to ping you because I modified my submission after your recent rule change. – Rainbolt – 2014-08-21T16:11:00.143

9

Walt Disney - Python 3

Walt waits until the shares hit rock bottom and then buys as much as his money allows. Then, when the price soars, he sells them all.

Based upon Disney's strategy when he 'survived' through the Wall Street Crash. Unfortunately, my program cannot build theme parks... If only...

Run:

python3 waltdisney.py

Code:

from sys import argv
import os

price=int(argv[1])
money=int(argv[2])
share=int(argv[3])

if os.path.exists('./buyingprice.txt'):
    f = open('buyingprice.txt', 'r')
    buyingprice=int(f.read())
    f.close()
else:
    buyingprice=0

if share > 0:
    if price > buyingprice*10:
        print('S'+str(share))
    else:
        print('W')
elif money > 0:
    if buyingprice==0:
        print('B10')
        m=open('buyingprice.txt', 'w')
        m.write(str(price))
        m.close()
    elif price <= buyingprice:
        print('B'+str(int(money/price)))
        g=open('buyingprice.txt', 'w')
        g.write(str(price))
        g.close()
    else:
        print('W')

Beta Decay

Posted 2014-08-20T15:35:56.150

Reputation: 21 478

You're missing a closing parenthesis on your first print line. – supersam654 – 2014-08-20T21:06:03.693

@supersam654 Oh yeah, thanks – Beta Decay – 2014-08-20T21:12:15.310

Can you point to a source for your assertion that Walt Disney actually used this strategy. Given there is a company named Walt Disney Co on the stock exchange it is difficult to search for, and Walt's wikipedia page doesn't mention it. – Michael – 2014-08-23T20:43:03.583

@Michael I got the information originally from my history teacher, so sorry if the source is a bit weak. – Beta Decay – 2014-08-23T22:52:16.353

8

Tommy

only knows what he has but is determined to risk everything on the market. If he can buy, he will. If he can't, he sells everything he has so he can next turn. (This will work well with extreme ones like DayTrader but will autocorrect if the value drops when he thinks it will grow.)

import java.math.BigInteger;

public class Tommy {
    public static void main(String[] args) {
        BigInteger Value = new BigInteger(args[0]);
        BigInteger Money = new BigInteger(args[1]);
        BigInteger Shares = new BigInteger(args[2]);

       if (Money.compareTo(Value)<1) {
           System.out.print("S" + Shares.toString());
       } else {
           System.out.print("B" + Money.divide(Value).toString());
       }
    }

}

Golfscript

This is the same code but if prefered this. I wrote the java after in case the BigInteger thing was needed. Use whatever is easier.

2$2$>{@@;;"S"\}{;\/"B"\} if

kaine

Posted 2014-08-20T15:35:56.150

Reputation: 536

For future reference, all numbers in GS are big integers. – Peter Taylor – 2014-08-21T12:39:54.370

I guess I could have just posted the original without worrying about it then! Good news. – kaine – 2014-08-21T13:04:16.857

I originally commented that I thought this was a duplicate of DayTrader, but then I realized that the behavior is only the same because of circumstances, and that they could diverge under other circumstances. Sorry if I offended anyone. Let's get rich together! – Rainbolt – 2014-08-21T14:41:47.610

@Rainbolt I wrote it GolfScript, read yours looking for duplicates before submitting, and actually used some or your code to write the Java version. The core part is not a duplicate (or I wouldn't have submitted it) but ends up being simular in these volitile markets. I'm not offended but if you feel it is too close I will request it be disqualified (but the code remain, I learned something writing it which is the whole point). As you have priority I wouldn't be offended even in that case. Note Earthquakers is almost identical to yours but does it differently (saves to file). – kaine – 2014-08-21T15:04:37.353

@kaine No no don't delete it. Like I said, I thought they were duplicates, but they definitely aren't. They are similar in behavior only because of the circumstances. I was wrong to post a comment claiming they were duplicates before I fully understood what yours was doing. – Rainbolt – 2014-08-21T15:06:20.883

6

BuyAndHold - C

#include <stdio.h>
#include <stdlib.h>

/* BuyAndHold
 * Code revised from OptoKopper's WaitForCrash.c
 */
int main(int argc, char *argv[]) {
    long long int share_price = strtoll(argv[1], NULL, 0);
    long long int money = strtoll(argv[2], NULL, 0);

    if (money >= share_price) {
        printf("B%lld\n", money / share_price);
    } else {
        printf("W\n");
    }

    return 0;
}

Compile with: gcc buyandhold.c -o buyandhold

Run it with ./buyandhold PRICE MONEY SHARES

Glenn Randers-Pehrson

Posted 2014-08-20T15:35:56.150

Reputation: 1 877

1Haha I was hoping someone would complement DayTrader with a BuyAndHold. Well done! – Rainbolt – 2014-08-20T18:41:27.037

6

Alfred Pennyworth - Python 2

While I was out on patrol one night, Alfred tried to create a stock trading program without my knowing. He thought he could hide it from me, but I found it and figured out what it did. Because I'm Batman. Now I've decided to enter it into a competition to teach him a lesson.

Money is no object to Alfred because I'm REALLY rich, but he's still smart about his trading. When he's out of shares, he buys as many as he can afford, regardless of market price. Then he sells 10 (or all remaining) shares every time the market price is higher than the price it was purchased at.

import argparse

parser = argparse.ArgumentParser(description="This is a private matter, Master Bruce. Learn how to make your own bed and I will tell you.")
parser.add_argument("Stuff", type=int, nargs='+', help="You don't need to know, Master Bruce.")

args=parser.parse_args()
vals=[]
for x in args:
    vals.append(x)

a=vals[0]
b=vals[1]
c=vals[2]

if c==0:
    x=1
    while x*a<b:
        x+=1
    print "B"+str(x)
    with open("lastval.txt", w) as f:
        f.write(a)

else:
    lastval=next(open("lastval.txt"))
    if a>lastval:print "S10" if c>10 else "S"+str(c)
    else:print 'W'

Run with: python GoAwayMasterBruce.py <args>

RageCage

Posted 2014-08-20T15:35:56.150

Reputation: 245

AttributeError: 'ArgumentParser' object has no attribute 'parseargs' Which version of Python does it need? – Peter Taylor – 2014-08-22T23:17:11.350

My mistake, there's an underscore. parse_args() – RageCage – 2014-08-25T18:11:59.747

5

NaiveBot

NaiveBot is new to all this "stock market" hooplah. He just assumes that when the price is going up he should buy, and when the price goes down he should sell. But he's no sap, he's got a trick up his sleeve! He only ever buys half of what he can afford, and only ever sells half of what he has.

No more living in a box under the freeway for NaiveBot!

<?php
$cur = array('price' => $argv[1], 'funds' => $argv[2], 'shares' => $argv[3]);

$cachefile = 'cache.json';
if( ! file_exists($cachefile) ) { $cache = array(); }
else { $cache = json_decode(file_get_contents($cachefile), true); }

// determine action
if( empty($cache) ) {
    $action = 'buy'; // always buy on first turn
} else if( $cur['price'] > $cache[count($cache)-1]['price'] ) {
    $action = 'buy';
} else if( $cur['price'] < $cache[count($cache)-1]['price'] ) {
    $action = 'sell';
} else {
    $action = 'hold';
}

// determine volume
if( $action == 'hold' ) {
    $volume = 0;
} else if( $action == 'buy' ) {
    // spend half my money on shares!
    $volume = floor(($cur['funds']/2)/$cur['price']);
} else if( $action == 'sell' ) {
    // sell half my shares!
    $volume = floor($cur['shares']/2);
}

// do a thing!
if( $action == 'hold' ) { echo 'W'; }
else if( $action == 'buy' ) { echo "B $volume"; }
else { echo "S $volume"; }
echo "\n";

$cache[] = $cur;
if( count($cache) == 50 ) { unlink($cachefile); } // wipe cache on last turn
else { file_put_contents($cachefile,json_encode($cache)); } // write cache

Run with php Naivebot.php $1 $2 $3, makes a cache.json in its current folder.

Sammitch

Posted 2014-08-20T15:35:56.150

Reputation: 509

5

Profit - Haskell

  1. Wait until the price is 1/maxValue
  2. Buy/Sell everything
  3. ????
  4. PROFIT!!!

import System.Environment (getArgs)

main = putStrLn . trade . map read =<< getArgs

trade :: [Integer] -> String
trade [p,m,s] -- not intended
  | p == 1 = "B" ++ (show m)
  | p == (fromIntegral $ (maxBound::Int) - 1) = "S" ++ (show s)
  | otherwise = "W"

Compile with ghc profit.hs and run with ./profit price money stock.

If it is not efficient enough, add -O3 flag, although it probably is overkill :D


Edit:

"optimised", now sells everything when the price is equal to Integer.MAX_VALUE.

ThreeFx

Posted 2014-08-20T15:35:56.150

Reputation: 1 435

Why not main = putStrLn . trade . map read =<< getArgs ? Less noisy – recursion.ninja – 2014-08-22T05:24:16.297

@awashburn Because I am not that well read regarding monads ;) – ThreeFx – 2014-08-22T06:16:24.533

I hope my comment helped you learn something new! – recursion.ninja – 2014-08-22T15:20:39.197

@ThreeFx there's a program for doing it, cabal install pointfree, now everyone will think you eat monads for breakfast. – Sean D – 2014-08-22T21:09:10.627

@SeanD Thanks, I'll have a look at it – ThreeFx – 2014-08-22T21:16:00.787

4

WaitForCrash

EDIT: fixed flaw in concept

EDIT: now using long long int

This is my first try. It behaves really simple and keeps one share to distinguish if it is the first round or a later one. In the first round nothing can be lost, so it buys shares. If it has shares it sells them. If eventually share prices drop to 10, it will buy again.

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[]) {
    long long int share_price = strtoll(argv[1], NULL, 0);
    long long int money = strtoll(argv[2], NULL, 0);
    long long int shares_owned = strtoll(argv[3], NULL, 0);

    if(shares_owned > 1) {
        printf("S%lld\n", shares_owned - 1);
    } else if (shares_owned == 0 || share_price == 10) {
        printf("B%lld\n", money / share_price);
    } else {
        printf("W\n");
    }

    return 0;
}

compile with: gcc waitforcrash.c -o waitforcrash

run it as ./waitforcrash PRICE MONEY SHARES

Optokopper

Posted 2014-08-20T15:35:56.150

Reputation: 309

Hope you don't mind I swiped your code to use as the basis for the BuyAndHold solution. BTW with long long ints, %d needs to be %Ld to avoid warnings (or is it %lld? Neither gives me a warning). – Glenn Randers-Pehrson – 2014-08-20T19:26:54.580

It's okay. Yeah I had the %lld in my code, must have forgotten them in the update, ty. – Optokopper – 2014-08-20T19:56:50.167

3

Earthquaker

Alternates between buying everything and selling everything (but one). It doesn't really aim to win as much as it does disrupt everyone else.

using System;
using System.IO;

namespace Earthquaker
{
    class Program
    {
        static void Main(string[] args)
        {
            if (args.Length < 3)
                return;

            int stockPrice = int.Parse(args[0]);
            int money = int.Parse(args[1]);
            int stocks = int.Parse(args[2]);

            bool shouldBuy = true;

            if (stocks != 0)
            {
                StreamReader sr = new StreamReader("brain.txt");
                if (sr.ReadLine() == "B")
                    shouldBuy = false;
                else
                    shouldBuy = true;
                sr.Close();
            }

            if (shouldBuy)
                Console.Write("B" + (money / stockPrice));
            else
                Console.Write("S" + (stocks - 1));

            StreamWriter sw = new StreamWriter("brain.txt", false);
            sw.Write(shouldBuy ? 'B' : 'S');
            sw.Close();
        }
    }
}

Compile with csc Earthquaker.cs. Run with Earthquaker.

Sean Latham

Posted 2014-08-20T15:35:56.150

Reputation: 1 423

.Net has System.IO.File.ReadAllText and WriteAllText, so you can simplify your history tracking slightly. – Peter Taylor – 2014-08-21T07:18:45.260

This crashes if it doesn't find its brain.txt file. – Peter Taylor – 2014-08-22T23:27:03.023

3

MonkeyTrader (in JAVA)

There's a saying that monkeys are good traders. I make the proof. Decisions between "buy" and "sell" are totally random.

import java.math.BigInteger;
import java.util.Random;

public class MonkeyTrader {
    /**
     * @param args the command line arguments containing the current 
     * market value, our current money, and our current shares
     */
    public static void main(String[] args) {
        BigInteger marketValue = new BigInteger(args[0]);
        BigInteger myMoney = new BigInteger(args[1]);
        BigInteger myShares = new BigInteger(args[2]);
        Random random=new Random();

        switch (random.nextInt(2)) {
        case 0:
            System.out.println("B" + myMoney.divide(marketValue));
            break;
        case 1:
            System.out.println("S" + myShares);
            break;
        }
    }
}

Bob Genom

Posted 2014-08-20T15:35:56.150

Reputation: 846

3

IntelliTrader

1st round he will sell his shares if they're a good price: $80 or more. Then he will sell off if the price is the same or better than the last price he sold at, buy if the price is the same or lower than the last price he bought at.

IntelliTrader.java

import java.io.*;
import java.math.BigInteger;
import java.util.Properties;

public class IntelliTrader {

    private static final String ROUND_NUM = "roundNum";
    private static final String LAST_BUY = "lastBuy";
    private static final String LAST_SELL = "lastSell";
    private static final String FILE = "IntelliTrader/memory.txt";

    private Properties memory;
    private int roundNum;

    private IntelliTrader(Properties memory) {
        this.memory = memory;
        roundNum = new Integer(memory.getProperty(ROUND_NUM, "0"));
    }

    public String evaluate(BigInteger market, BigInteger money, BigInteger shares) {
        String command = "W";
        if (roundNum == 0) {
            if (market.intValue() > 80) {
                command = sell(market, shares);
            } else {
                command = buy(market, money);
            }
        } else {
            if (market.compareTo(new BigInteger(memory.getProperty(LAST_SELL, "0"))) >= 0) {
                command = sell(market, shares);
            } else if (market.compareTo(new BigInteger(memory.getProperty(LAST_BUY, "999999999"))) <= 0) {
                command = buy(market, money);
            }
        }
        return command;
    }

    private String buy(BigInteger cost, BigInteger money) {
        memory.setProperty(LAST_BUY, cost.toString());
        return "B" + money.divide(cost).toString();
    }

    private String sell(BigInteger cost, BigInteger shares) {
        memory.setProperty(LAST_SELL, cost.toString());
        return "S"+shares.toString();
    }


    public static void main(String[] args) {    
        BigInteger marketValue = new BigInteger(args[0]);
        BigInteger myMoney = new BigInteger(args[1]);
        BigInteger myShares = new BigInteger(args[2]);

        Properties memory = new Properties();
        try {
            memory.load(new FileReader(FILE));
        } catch (IOException e) {
            //ignore, file probably doesn't exist yet
        }

        int roundNum = new Integer(memory.getProperty(ROUND_NUM, "0"));
        if (roundNum > 49) {
            roundNum = 0;
            memory.setProperty(ROUND_NUM, "0");
            memory.setProperty(LAST_BUY, "0");
            memory.setProperty(LAST_SELL, "0");
        }

        IntelliTrader it = new IntelliTrader(memory);
        String command = it.evaluate(marketValue, myMoney, myShares);
        System.out.println(command);

        roundNum++;
        memory.setProperty(ROUND_NUM, ""+roundNum);
        try {
            memory.store(new FileWriter(FILE), "IntelliTrader memory properties");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Compile with javac IntelliTrader. Run with java -cp "IntelliTrader" IntelliTrader

Benny

Posted 2014-08-20T15:35:56.150

Reputation: 123

In my tests this seems to be the second best trader. – Peter Taylor – 2014-08-23T07:08:05.893

2

LeesonLearnt v1.1 (Java, conservative)

Since the rule change means that we now start with some shares, there's no longer a guaranteed best first move, so I've simplified this by removing the special case for the first turn.

import java.math.BigInteger;

public class LeesonLearnt {
    private static final BigInteger THRESHOLD = new BigInteger("100");

    public static void main(String[] args){
        BigInteger price = new BigInteger(args[0]);
        BigInteger capital = new BigInteger(args[1]);
        BigInteger shareholding = new BigInteger(args[2]);

        BigInteger affordable = capital.divide(price);

        // In the long run, the shares will probably lose all their value.
        // But if they're cheap, buying them will pump them and they can be sold at a profit.
        // The target amount of our value held in shares varies exponentially with their price.
        BigInteger targetShareholding = price.compareTo(THRESHOLD) > 0
            ? BigInteger.ZERO
            : affordable.add(shareholding).shiftRight(price.intValue() - 1);
        if (targetShareholding.compareTo(shareholding) <= 0) {
            System.out.println("S" + shareholding.subtract(targetShareholding));
        }
        else {
            BigInteger diff = targetShareholding.subtract(shareholding);
            System.out.println("B" + diff.min(affordable));
        }
    }
}

Invoke as

java -cp LeesonLearnt LeesonLearnt <price> <capital> <shareholding>

Peter Taylor

Posted 2014-08-20T15:35:56.150

Reputation: 41 901

2

theAnswerOfLifeIs42.py

My program loves the number 42

The rule is simple: I can either buy 42 stock or sell 42 stock.

import sys
price, money, shares = [int(arg) for arg in sys.argv[1:]]

if money>42*price:
 print "B 42"
else:
 print "S 42"

Realdeo

Posted 2014-08-20T15:35:56.150

Reputation: 421

1

Ol' Timer - Fortran 77

This old man is going to waste away his pension after sixty years of working as an office clerk. During his old age, however, he became quite blind, so he can only see he first number of each argument, so he estimates the price. His method is similar to that of Walt's, except Ol' Timer is a little more careless.

Because of the problems with the Fortran printing, I've written a Python program which will help. The program takes the arguments supplied and pipes them through to the Fortran program. Then, the Python program reformats the output to the expected format.

Compile:

gfortran oltimer.for -o oltimer.exe

Run:

python3 assistant.py [arg1] [arg2] [arg3]

Python Assistant Code:

from subprocess import Popen, PIPE
import sys, re

ret = Popen('./oltimer.exe '+sys.argv[1]+' '+sys.argv[2]+' '+sys.argv[3], stdout=PIPE, shell=True).communicate()[0].decode('utf-8')
value=re.findall(r'\d+',ret)

if 'W' in ret:
     print('W')

elif 'B' in ret:
     print('B'+str(value[0]))

elif 'S' in ret:
     print('S'+str(value[0]))

FORTRAN Main Code:

      PROGRAM OLTIMER
C DEFINE VARIABLES
          INTEGER :: PRICE
          INTEGER :: STOCK
          INTEGER :: MONEY
          INTEGER :: INTBUFFER
          CHARACTER :: BUFFER
C GET CMD ARGUMENTS & CONVERT TO INT
          CALL getarg(1, BUFFER)
          READ (BUFFER, '(i10)') PRICE
          CALL getarg(2, BUFFER)
          READ (BUFFER, '(i10)') MONEY
          CALL getarg(3, BUFFER)
          READ (BUFFER, '(i10)') STOCK
C EVALUATE SITUTATION AND MAKE DECISION
          IF (PRICE.LT.5) THEN
            IF (MONEY.GT.0) THEN
                INTBUFFER=(MONEY*50)/(5-PRICE)
                PRINT*,'B',INTBUFFER
            ELSE
                PRINT*,'W'
            END IF
          ELSE
            IF (PRICE.GT.9) THEN
                IF (STOCK.GT.0) THEN
                    INTBUFFER=STOCK/(PRICE-9)
                    PRINT*,'S',INTBUFFER
                ELSE
                    PRINT*,'W'
                END IF
            ELSE
                PRINT*,'W'
            END IF
          END IF      
      END PROGRAM

Beta Decay

Posted 2014-08-20T15:35:56.150

Reputation: 21 478

1Given that you need Python anyway, and that there are other answers in Python but none in Fortran, do you not think it would make sense to implement the whole thing in Python and reduce the burden of compilers which OP has to install? – Peter Taylor – 2014-08-21T22:54:00.100

@Peter I would but I thought it'd be fun to have a completely different language and see how it performs. – Beta Decay – 2014-08-22T07:14:39.737

1

Dollar Cost Averager - Python 3

This strategy attempts to use dollar cost averaging by buying (as close as it can to) a fixed amount of money (arbitrarily set at 150 so that it'll probably use up most of its money by the end) each turn.

import sys
price, money, shares = [int(arg) for arg in sys.argv[1:]]
target_per_day = 150
buy = round(min(target_per_day, money) / price)
if buy * price > money:
    buy -= 1
if buy > 0:
    print("B" + str(buy))
else:
    print("W")

Tim S.

Posted 2014-08-20T15:35:56.150

Reputation: 615

1

Cash Is King - Python 2 or 3

This guy is very pessimistic about the stock market. He'd rather keep his money in cash where he can keep it safe under his mattress.

import sys
shares = int(sys.argv[3])
if shares > 0:
    print("S" + str(shares))
else:
    print("W")

Tim S.

Posted 2014-08-20T15:35:56.150

Reputation: 615

1

Slow and Steady

As long as it has money, it buys $165 worth of shares. Otherwise it sells all of its shares to get more money, to buy more shares. On the 50th round it makes sure to sell all shares, because in the end we want cash.

import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.math.BigInteger;
import java.nio.file.Files;
import java.nio.file.Paths;

public class SlowAndSteady{
    public static void main(String[] args) {
        BigInteger price = new BigInteger(args[0]);
        BigInteger cash= new BigInteger(args[1]);
        long shares= Long.parseLong(args[2]);
        BigInteger number = new BigInteger("165");
        String count = "0";


        try {
            count = new String(Files.readAllBytes(Paths.get("counter.txt")));
        } catch (IOException e) {

        }

        int c = Integer.parseInt(count)+1;

        if (c >= 50)
        {
            System.out.println("S" + shares);
            c=0;
        }

        else if(cash.compareTo(number) > 0)     System.out.println("B" + (number.divide(price)));

        else System.out.println("S" + shares);


        try {
            Writer wr = new FileWriter("counter.txt");
            wr.write(Integer.toString(c));
            wr.close();
        } catch (IOException e) {
        }
   }
}

Compile with javac SlowAndSteady.java. Run with java -cp "SlowAndSteady" SlowAndSteady. Counter should reset between rounds, but if the file is deleted, it will also work.

Red_Shadow

Posted 2014-08-20T15:35:56.150

Reputation: 201

1

Time is Right - Python 3

I got bored so I wrote another entrant...

This young entrepeneur lives his life by the clock. When the time is right, he makes a decision. He also annoyingly uses French out of context... ;)

Run:

python3 timeisright.py [arg1] [arg2] [arg3]

Code:

import sys, time

price = int(sys.argv[1])
money = int(sys.argv[2])
shares = int(sys.argv[3])

lheure = int(time.time())

if lheure % 3 == 0:
    print('S'+str(int(shares/4)))
elif lheure % 3 == 1:
    print('B'+str(int(money/4*price)))
else:
    print('W')

Beta Decay

Posted 2014-08-20T15:35:56.150

Reputation: 21 478

1

BuyHighSellLow

Tracks the market history and buys when the price low and sells when it's high.

import sys

storage = 'BuyHighSellLow'
turn = 0
turns = 50
max_start_price = 150
limit = 0.25

price = int(sys.argv[1])
money = int(sys.argv[2])
shares = int(sys.argv[3])

# Calculate average price
with open(storage+'/history', mode='a') as f:
            pass # Create file if it doesn't exist
with open(storage+'/history', mode='r') as f:
    values = list((int(line) for line in f))
    turn = len(values) + 1
    if turn > turns: turn = 1
    if turn == 1:
            average = max_start_price + 1
            turn = 1
    else:
            average = sum((value / turn for value in values))

# Buy low and sell high
if price < average:
    print('B' + str(int(limit * money / price)))
elif price > average:
    print('S' + str(int(limit * shares)))
else:
    print('W')

# Save history
if turn == 1: mode='w'
else: mode = 'a'
with open(storage+'/history', mode=mode) as f:
    print(price, file=f)

Run with:

python3 BuyHighSellLow/buyhighselllow.py

ccarton

Posted 2014-08-20T15:35:56.150

Reputation: 446

0

Test1 Trader

public class Test1 {

    public static void main(String[] args){
        int marketValue = Integer.parseInt(args[0]);
        int myMoney = Integer.parseInt(args[1]);
        int myShares = Integer.parseInt(args[2]);

        //Buy 10 if we don't have any.
        if(myShares <= 0){
            System.out.println("B10");
        }else{
            System.out.println("S1");
        }
    }
}

Compile with javac Test1.java run with java -cp "Test1" Test1

spocot

Posted 2014-08-20T15:35:56.150

Reputation: 606

0

Hedgehog - python2.7

This is mostly to reserve the name

from __future__ import print_function
from sys import argv

storage = 'prices.txt'
price,cash,shares = map(long, argv[1:])
turn = 1
buy = lambda x: print('B%d' % long(x))
sell = lambda x: print('S%d' % long(x))
cashtoshares = lambda c: long(c/price)
TURN,PRICE,CASH,SHARES=range(4)

try:   
    data = [map(long, line.split()) for line in open(storage)]
    if data:
        turn = data[-1][TURN] + 1
except IOError:
    pass
with open(storage, 'a') as pricelist:
    pricelist.write('%d %d %d %d\n' % (turn, price, cash, shares))

if turn == 1:
    buy(cashtoshares(cash)) # convert all cash into shares
elif price == 1:
    buy(cashtoshares(cash)) # cannot buy at a better deal
elif price < 10:
    buy(cashtoshares(cash/2))
elif shares < 10:
    buy(cashtoshares(cash/2))
else:
    sell(shares/2)

Run as

python hedgehog.py PRICE CASH SHARES

Moop

Posted 2014-08-20T15:35:56.150

Reputation: 723

0

BuyAndSell - C

Similar but not a duplicate of Tommy. Alternates between panic buying as much as possible and selling everything. Almost a duplicate of Earthquaker which retains one share while BuyAndSell sells all shares. BuyAndSell takes no action when it has no shares to sell but hasn't got enough money to buy one share.

/* BuyAndSell
 * Code revised from OptoKopper's WaitForCrash.c and my BuyAndHold.c
 * Alternates between buying as many shares as possible and selling everything
 * Run it as ./buyandsell PRICE MONEY SHARES
 */
int main(int argc, char *argv[]) {
    long long int share_price = strtoll(argv[1], NULL, 0);
    long long int money = strtoll(argv[2], NULL, 0);
    long long int shares = strtoll(argv[3], NULL, 0);

    if (money >= share_price) {
        printf("B%lld\n", money / share_price);
    } else {
        if (money == 0) {
            printf("S%lld\n", shares);
        } else {
            printf("W\n");
        }
    }

    return 0;
}

Compile with "gcc buyandsell.c -o buyandsell"

Run as "./buyandsell PRICE MONEY SHARES

Glenn Randers-Pehrson

Posted 2014-08-20T15:35:56.150

Reputation: 1 877

0

Gorge Soros

price = ARGV.shift
money = ARGV.shift
stock = ARGV.shift
if price*10<money
  puts "B10"
else
  puts "S#{stock}"
end

Buys slowly, than sells everything in an attempt to crash the market.

Run with:Soros.rb price money stock

MegaTom

Posted 2014-08-20T15:35:56.150

Reputation: 3 787

1It explicitly says in the question text Do not intentionally create programs to crash the simulation. – Beta Decay – 2014-09-01T17:25:50.200

@BetaDecay I meant dont try to crash the controller. Trying to crash the market is part of the game. – spocot – 2014-09-01T17:38:35.093

@spocot Oh, I thought that you meant to not create programs to crash the market. You should phrase that differently to prevent more confusion. – Beta Decay – 2014-09-01T17:46:18.720