Stock Exchange KoTH

23

7

The stock market is all about the speed of knowledge. Unlike previous challenges, the current stock price is not random: it is determined by those playing the game. If you can identify an under-priced stock before anybody else, then you've written yourself a money-making program.

Price refers to the how much people are trading the stock for, while Value refers to the amount the stock is worth at the end of the game.

Each player starts with 1000 of each stock, and 0 relative net worth. Each stock has a secret value, and your score at the end of the game is (stockValue for each ownedStock) + netWorth. Your net worth can be negative. In an N-player game, there are N stocks.

Steps:

The game follows the following steps:

  1. You are given the secret value of a single stock.
  2. You make an offer to sell X of Y stock for $Z
  3. All players are given the offers, and each may choose one to accept
  4. All players are informed of accepted offers
  5. Go back to step 2

Each of the steps are given in detail below:

  1. void secretValue(int stockType, int value):

    • The value you learn is not revealed to any other player.
    • The value is between 0 and 1000
    • Low values are more like to occur than high values (squared uniform distribution)
  2. Offer makeOffer(List<Stock> currentStock)

    • You can return null to make no offer.
  3. Offer acceptOffer(List<Offer> offers)

    • You can return null to accept none of them
    • If there are no available offers, this will not be called
    • If you accept, your net worth goes down by $Z (can go negative) and receive X of Y stock. The opposite occurs with the seller.
    • If you accept an offer, the exchange will occur immediately, and the offer will be removed so additional players cannot accept it.
  4. void acceptedOffers(List<Offer> offers)

    • Includes your accepted offers as well

Static variables or writing to files is not allowed. (No persistent data from game to game) Non-serious contenders are allowed.

Interfaces:

public final class Stock {
    public Stock(int stockType, int amount);
    public int getType();
    public int getAmount();
    public Stock minus(Stock other);
    public Stock plus(Stock other);
    public Stock minus(int amount);
    public Stock plus(int amount);
    public Stock setAmount(int amount);
}
public class Offer {
    public Offer(Stock offer, int payment);
    public Stock getOffer();
    public int getPayment();
}

Non-Java submissions:

  • All calls consist of two lines: The first line is the function being called: SecretValue, MakeOffer, AcceptOffer, AcceptedOffers, SetRandom, and the second line containing the actual data.
  • Stocks are formatted with a : delimiter: stockType:stockAmount.
  • Offers are formatted with a @ delimiter: offer@price
  • Lists are formatted with a ; delimiter
  • SecretValue is formatted with a : delimiter: stockType:value
  • RandomSeed is used to make your submission deterministic. If your submission uses randomness, please use the integer value passed as the seed!
  • All function calls need a response. If the response is null or void, return an empty string.
  • Please include a command.txt that gives the command line arguments to run your submission

Scoring

Games consisting of 1000 turns will be run multiple times. Players will be scored according to the ELO system, and paired with players of similar skill levels. The player with the highest final ELO score wins! (I've modified the system so that each game, ELO scores are updated for each player pairing)

The controller includes an autodownloader, so please start your submission with a header: Name, Language. If your submission is not in Java, each code block should start with the name of the file. (excluding the command file, which should be the first block in your post)

Running

There are 2 ways to run this project:

  1. Download the source code, compile and run. You can find the source on Github. Run git clone --recursive https://github.com/nathanmerrill/StockExchange.git

  2. Download the JAR executable. Submissions should be placed in your current working directory in the /submissions folder. You can download just the JAR, just the submissions, or both

Pass in run to run the project (default option), or pass in download to download all submissions so far from this question.

Scoreboard

1.  1308.1220497323848  Cheater
2.  1242.0333695640356  InsideTrader
3.  1158.3662658295411  UncleScrooge
4.  1113.8344000358493  BlackMarket
5.  1051.8370015258993  DartMonkey
6.  983.0545446731494   WarGamer
7.  939.457423938002    Spammer
8.  901.4372529538886   DumbBot
9.  859.0519326039137   ShutUpAndTakeMyMoney
10. 852.9448222849587   VincentKasuga
11. 718.2112067329083   Profiteer

Nathan Merrill

Posted 2016-08-29T21:13:42.407

Reputation: 13 591

stock properties aren't public, instruct to use getter methods – noɥʇʎԀʎzɐɹƆ – 2016-08-29T22:30:06.373

@AgentCrazyPython better? – Nathan Merrill – 2016-08-29T22:36:31.820

are current prices correlated to previous prices? – noɥʇʎԀʎzɐɹƆ – 2016-08-29T22:38:55.910

The "price" is simply the amount people are selling stock for. Values of stock change from game to game. – Nathan Merrill – 2016-08-29T22:44:58.960

Btw, trueskill is a better ranking system than the elo system. You can find an implementation here.

– TheNumberOne – 2016-08-29T23:10:33.060

ability to accept multiple offers, please. – noɥʇʎԀʎzɐɹƆ – 2016-08-29T23:13:31.780

API to get number of turns. – noɥʇʎԀʎzɐɹƆ – 2016-08-29T23:19:39.363

@Accepting Accepting multiple offers won't be supported. To get number of turns, StockExchange.NUM_EXCHANGES – Nathan Merrill – 2016-08-29T23:23:41.850

1A chat room would be appreciated. – TheNumberOne – 2016-08-29T23:25:01.030

"Published formulas for Trueskill are not complete" – Nathan Merrill – 2016-08-29T23:25:12.913

2http://chat.stackexchange.com/rooms/44660/stock-exchange – Nathan Merrill – 2016-08-29T23:26:07.127

Wikipedia is wrong. A full implementation is here. A full description of the formulas used is here.

– TheNumberOne – 2016-08-29T23:27:01.580

I need to know when it ends to help my new bot... – noɥʇʎԀʎzɐɹƆ – 2016-08-29T23:41:51.693

@AgentCrazyPython you can use a member variable to keep track of the number of turns. MakeOffer() will be called exactly 1000 times – Nathan Merrill – 2016-08-29T23:44:22.400

if nobody makes an offer for a stock, then what's the price at the end? Critical to my bot. – noɥʇʎԀʎzɐɹƆ – 2016-08-29T23:48:46.627

The value at the end is determined randomly, and is independent of the prices being offered. You get to know the end value of exactly 1 stock. – Nathan Merrill – 2016-08-29T23:51:16.497

So, if nobody buys a stock, what's it's value? Average of offers? – noɥʇʎԀʎzɐɹƆ – 2016-08-29T23:56:59.910

It is determined by the controller and not shown to your program. – TheNumberOne – 2016-08-29T23:57:42.873

@NathanMerrill OH I GET IT! Value is different. Then my market corner strat doesn't work.............. – noɥʇʎԀʎzɐɹƆ – 2016-08-29T23:58:52.680

Exact formula is Math.ceil(Math.pow(random.nextDouble(), 2) * 1000) – TheNumberOne – 2016-08-29T23:59:03.047

Well it might work because of dumb bots... but not as well... – noɥʇʎԀʎzɐɹƆ – 2016-08-30T00:02:02.897

something that can work is a program that make averages on stock market shares (=="azioni") for find if there are unusual buy or sale of these stock market shares. If there are many buy on one stock share: computer has to buy that stock market share. if there are many sale on one stock market share: sale that one. this is because I as the program computer not have enought info for sale or buy, no sure info, no true info or important info on what is going on in the market. Yes it is better if one have some info true on that market and use these. i don't know translation is right... – RosLuP – 2016-08-30T18:28:22.467

@RosLuP if I understand you, you are saying to sell when others are selling, and buy when others buy. This sounds like a good strategy! – Nathan Merrill – 2016-08-30T18:31:22.603

@Nathan: yes if i have no good info: selling what other people sell, buy what they are buying (if there are big evidence on these). But i'm not an expert so i can make it wrong... – RosLuP – 2016-08-30T18:34:26.007

@TimmyD 1000 turns. Added, thanks. – Nathan Merrill – 2016-08-30T19:18:35.023

Quick clarification: when accepting offers, the end value of that stock will be (stock.amount * stock.secretValue) yes? – Socratic Phoenix – 2016-08-30T19:21:28.630

@SocraticPhoenix correct – Nathan Merrill – 2016-08-30T19:22:23.277

In the controller, StockExchange.nextStep, you shuffle the players before making offers to them, but I think you should also shuffle the offers (either once or before each call to giveOffers). – Peter Taylor – 2016-08-31T10:20:42.237

@PeterTaylor You're right. The order of offers matters (only slightly), but good catch. – Nathan Merrill – 2016-08-31T12:06:11.887

poking question – noɥʇʎԀʎzɐɹƆ – 2016-09-12T19:25:21.163

Answers

13

Cheater, Java

Tries to sell nothing for money.

import java.util.List;
import java.util.Random;
import com.ppcg.stockexchange.*;

public class Cheater extends Player {
    private Random random = new Random();

    public Offer acceptOffer(List<Offer> offers) {
        return null;
    }

    public Offer makeOffer(List<Stock> currentStock){
        Stock stock = randomStock();
        int price = random.nextInt(100) + 1;
        return new Offer(stock.setAmount(0), price);
    }
}

CommonGuy

Posted 2016-08-29T21:13:42.407

Reputation: 4 684

5And that's how the great depression happens! I could see this breaking a lot of bots that buy cheap... – Socratic Phoenix – 2016-08-31T09:53:22.130

Congrats! I fixed a critical bug, and now this bot is in first! – Nathan Merrill – 2016-09-01T18:29:52.383

Wow, the other bots are not good enough then, that this dumb bot can win – justhalf – 2016-09-02T02:06:26.183

8

WarGamer, Java

Upon a perfunctory examination of the rules I have decided that the primary winning move is not to play. Anyone offering to sell stock likely knows the price and will profit from the sale. It can be toggled so it will make "joke" offers to sell a stock for Integer.MAX_VALUE dollars hoping shut up and take my money will bite.

import java.util.List;
import com.ppcg.stockexchange.*;
import com.ppcg.kothcomm.game.AbstractPlayer;
import com.ppcg.kothcomm.utils.Tools;

import java.util.List;

public class WarGamer extends Player {
static final boolean FRAUD = false;
    /**
     * @param offers All available offers
     * @return An offer you want to accept, or null if you want to accept neither.
     */
    public Offer acceptOffer(List<Offer> offers){
        return null;
    }

    public Offer makeOffer(List<Stock> currentStock){
    if(FRAUD)
    return new Offer(new Stock(0,1),Integer.MAX_VALUE);
        //defraud shut up and take my money            
    return null;
    }
}

Rohan Jhunjhunwala

Posted 2016-08-29T21:13:42.407

Reputation: 2 569

1This would probably work fine, except I expect there will be entries that dumb-luck their way slightly higher. There usually are. – Geobits – 2016-08-29T21:40:30.287

This doesn't compile. – Rainbolt – 2016-08-29T21:46:55.167

@Rainbolt it has the dependencies. You need to make sure are present. – Rohan Jhunjhunwala – 2016-08-29T21:49:07.957

@Rainbolt what compiler error are you getting – Rohan Jhunjhunwala – 2016-08-29T21:49:21.487

Exception in thread "main" java.lang.RuntimeException: Error on line 8: com.ppcg.stockexchange.WarGamer is not abstract and does not override abstract method makeOffer(java.util.List<com.ppcg.stockexchange.Stock>) in com.ppcg.stockexchange.WarGamer – Nathan Merrill – 2016-08-29T21:54:14.337

abstract cause the compilation to fail; a valid version of this code is http://pastebin.com/WmaZt8rL – TuxCrafting – 2016-08-29T22:12:11.323

@Rainbolt sorry – Rohan Jhunjhunwala – 2016-08-29T22:33:05.913

@Geobits it now defrauds shut up and take my money for max profit – Rohan Jhunjhunwala – 2016-08-29T22:44:59.040

1I'm not sure the part where you trick the other joke bot is in the right spirit... – Maltysen – 2016-08-29T23:13:18.323

@Maltysen your right. It was a bit cheaty of me – Rohan Jhunjhunwala – 2016-08-29T23:36:10.037

@Maltysen I'll add a flag so that "feature" can be toggled – Rohan Jhunjhunwala – 2016-08-29T23:36:31.690

Your if statement made it not compile. Remove the semicolon after it. Also, remove the package. – Nathan Merrill – 2016-08-30T00:14:58.510

Also, please use the import statements from DumbBot. Your current imports are wrong. – Nathan Merrill – 2016-08-30T00:22:26.900

@NathanMerrill I am nothing but my IDE, sorry. – Rohan Jhunjhunwala – 2016-08-30T01:20:38.047

Fixed the bugs mentioned let me know if there are any more problems – Rohan Jhunjhunwala – 2016-08-30T01:20:56.603

According to the koth tag wiki, strategies that specifically target other bots are at the least discouraged, if not disallowed by default

– Socratic Phoenix – 2016-08-30T02:49:52.860

@SocraticPhoenix that is why FRAUD is set to false – Rohan Jhunjhunwala – 2016-08-30T02:57:29.730

You still need to remove the package statement. – Nathan Merrill – 2016-08-30T11:50:27.327

@NathanMerrill fixed – Rohan Jhunjhunwala – 2016-08-30T12:25:11.753

5

ShutUpAndTakeMyMoney, Java

import java.util.List;
import com.ppcg.stockexchange.*;

public class ShutUpAndTakeMyMoney extends Player {
    public ShutUpAndTakeMyMoney() {}

    public Offer acceptOffer(List<Offer> offers) {
        try {
            return offers.get(0);
        } catch (Exception ex) {
            return null;
        }
    }
    public Offer makeOffer(List<Stock> stock) {
        return null;
    }
}

It accepts any offer.

TuxCrafting

Posted 2016-08-29T21:13:42.407

Reputation: 4 547

Actually thank you for your bot – Rohan Jhunjhunwala – 2016-08-29T22:24:51.553

6have +1 for making me rich – Rohan Jhunjhunwala – 2016-08-29T22:44:33.820

1

It seems to me that this isn't really compatible with the requirement that every answer should "be a serious contender for the winning criteria in use".

– Peter Taylor – 2016-09-01T16:32:21.827

2@PeterTaylor It's serious, it's 5th on the leaderboard – TuxCrafting – 2016-09-01T16:35:51.167

This is arguably a suicidal entry, as it's reasonable to expect that other bots will sell stocks for more than they are worth, leading to you buying stock for well over its actual price.

– Mego – 2016-09-02T04:27:09.273

4

DumbBot, Java

Use this bot when creating your own. Offers its secret stock at a discounted price.

import java.util.List;
import com.ppcg.stockexchange.*;
public class DumbBot extends Player {
    public Offer acceptOffer(List<Offer> offers) {
        return null;
    }
    public Offer makeOffer(List<Stock> currentStock){
        return new Offer(currentStock.get(secretStockType).setAmount(1), Math.max(1, secretStockValue - 5));
    }
    public void secretValue(int stockType, int value) {
        super.secretValue(stockType, value);
    }
    public void acceptedOffers(List<Offer> acceptedOffers) {
    }
}

Nathan Merrill

Posted 2016-08-29T21:13:42.407

Reputation: 13 591

1Seems like I want him handling my money – Rohan Jhunjhunwala – 2016-08-29T22:33:30.977

please make this community wiki – noɥʇʎԀʎzɐɹƆ – 2016-08-30T22:30:57.483

@AgentCrazyPython why? – Nathan Merrill – 2016-08-30T22:56:44.337

@NathanMerrill rep profiting off of this dummy bot – noɥʇʎԀʎzɐɹƆ – 2016-08-30T23:08:54.567

@AgentCrazyPython I don't really want people to be editing this... I don't really care about rep, so feel free to not upvote (or downvote) – Nathan Merrill – 2016-08-30T23:15:45.837

It seems to me that this isn't really compatible with the requirement that every answer should "be a serious contender for the winning criteria in use".

– Peter Taylor – 2016-09-01T16:32:04.927

@PeterTaylor you're right. When I'm constructing games, I select players of similar skill, so I'm ok with non-serious contenders. I'll add that to the question. – Nathan Merrill – 2016-09-01T17:01:56.817

3

python_starter, Python 3

Use this as a starting point for any python (or other language) programs

Accepts a random offer.

Command file:

python3 starter.py

Program:

starter.py
import random
from functools import total_ordering


LIST_DELIMITER = ';'
STOCK_DELIMITER = ':'
OFFER_DELIMITER = '@'


@total_ordering
class Stock:
    @staticmethod
    def parse(string: str):
        return Stock(*map(int, string.split(STOCK_DELIMITER)))

    def __init__(self, stock_type: int, amount: int):
        self.type = stock_type
        self.amount = max(amount, 0)

    def __str__(self):
        return str(self.type)+STOCK_DELIMITER+str(self.amount)

    def __eq__(self, other):
        return self.amount == other.type

    def __lt__(self, other):
        return self.amount < other.amount

    def update(self, amount) -> 'Stock':
        return Stock(self.type, amount)

    def __mul__(self, other: int) -> 'Stock':
        return self.update(self.amount*other)

    def __floordiv__(self, other: int) -> 'Stock':
        return self.update(self.amount//other)

    def __add__(self, other: int) -> 'Stock':
        return self.update(self.amount+other)

    def __sub__(self, other: int) -> 'Stock':
        return self.update(self.amount-other)


class Offer:
    @staticmethod
    def parse(string: str) -> 'Offer':
        try:
            offer, payment = string.split(OFFER_DELIMITER)
        except ValueError:
            raise Exception("Cannot unpack "+string)
        return Offer(Stock.parse(offer), int(payment.strip()))

    def __init__(self, offer: Stock, payment: int):
        self.offer = offer
        self.payment = payment

    def __str__(self):
        return str(self.offer)+OFFER_DELIMITER+str(self.payment)


def read_stock_value(value: str):
    global hidden_price, hidden_stock
    stock, price = value.split(STOCK_DELIMITER)
    hidden_price = float(price)
    hidden_stock = int(stock)


def process_input():
    handlers = {
        "SecretValue": read_stock_value,
        "RandomSeed": read_seed,
        "MakeOffer": make_offer,
        "AcceptOffer": accept_offer,
        "AcceptedOffers": accepted_offers,
    }
    method = input().strip()
    data = input().strip()
    output = handlers[method](data)
    if output is not None:
        print(str(output))
    else:
        print()


def read_seed(seed: str):
    random.seed(int(seed))


def start():
    while True:
        process_input()


hidden_stock = None
hidden_price = None


def make_offer(current_stock: str):
    current_stock = map(Stock.parse, current_stock.split(LIST_DELIMITER))
    pass


def accept_offer(available_offers: str):
    available_offers = list(map(Offer.parse, available_offers.split(LIST_DELIMITER)))
    return random.sample(available_offers, 1)[0]


def accepted_offers(offers: str):
    offers = map(Offer.parse, offers.split(LIST_DELIMITER))
    pass


if __name__ == "__main__":
    start()

Nathan Merrill

Posted 2016-08-29T21:13:42.407

Reputation: 13 591

1this is too complicated. – noɥʇʎԀʎzɐɹƆ – 2016-08-29T23:37:27.080

2Most of it is helper stuff. If you're writing it in python, you just need to implement the bottom 3 functions. – Nathan Merrill – 2016-08-29T23:38:36.867

what does it do? – noɥʇʎԀʎzɐɹƆ – 2016-08-30T23:30:46.557

The bot accepts a random stock. The helper stuff does parsing/encoding, as well as provides classes for Offer/Stock. – Nathan Merrill – 2016-08-30T23:31:47.123

...and it's winning :/ – noɥʇʎԀʎzɐɹƆ – 2016-08-30T23:32:56.830

how to use boilerplate? – noɥʇʎԀʎzɐɹƆ – 2016-09-01T00:15:49.113

Copy everything, and implement the bottom 3 functions. – Nathan Merrill – 2016-09-01T00:42:06.780

yes, but what's the API for stock and offfer classes? – noɥʇʎԀʎzɐɹƆ – 2016-09-01T01:00:27.557

Basic mathematical operations with stock will work (stock*3, for example). if you return a stock or offer, it'll automatically get stringified. stock.amount to get the amount, stock.type to get the type. offer.offer to get the stock getting offered, and offer.payment to get the amount its getting sold for – Nathan Merrill – 2016-09-01T01:02:55.757

3

VincentKasuga, Java

Not sure if my Java is valid. Please review.

How it works

- if you own all the stocks, you can set the price of the stock. You are the only seller. 1. Buy all the stocks. 2. Set the price of all the stocks to be super high on the last tick. 3. PROFIT! - This isn't normally possible because...

  • The price would usually skyrocket to infinity... but there's a limit!
  • ... (more reasons to come)

How it works, v2

  • The price is artificially set at a maximum by some anarchist state
  • This is bad economically

Todo

  • Corner the market multiple times! Muahaha!

FAQ

Q: Who's Vincent Kasuga?

A: He bought all the onions and onion futures in the United States. (put them all in a secret warehouse) Held the industry at ransom - give me X million or I'll set the price sky-low and you'll all go bankrupt.

But he didn't stop there.

Then, he secretly shorted the onion ETF (bet that it would go down). He sold all the onions at one time, physically delivering them in thousands of trucks to the stock exchange. The onion bag cost less than the onions. He made millions AGAIN. In short, the Hudson river overflowed with onions.

He's a real person.

The code

import com.ppcg.stockexchange.Offer;
import com.ppcg.stockexchange.Player;
import com.ppcg.stockexchange.Stock;

import java.util.List;

public class VincentKasuga extends Player {
    private int knownStock;
    private int knownPrice;
    private int corneredStockType = -1;
    private int corneredLikelehood = 0;
    private boolean marketCornered;
    private int ticks;

    public Offer acceptOffer(List<Offer> offers) {
        if (!marketCornered) {
            Offer maxOffer = null;
            int maxAmount = 0;
            if (corneredStockType == -1) {
                for (Offer offer: offers) {
                    if (offer.getOffer().getAmount() > maxAmount) {
                        maxAmount = offer.getOffer().getAmount();
                        maxOffer = offer;
                    }
                }
            } else {
                for (Offer offer: offers) {
                    if (offer.getOffer().getAmount() > maxAmount && offer.getOffer().getType() == corneredStockType) {
                        maxAmount = offer.getOffer().getAmount();
                        maxOffer = offer;
                    }
                }
            }


            if (maxOffer == null) {
                // may have cornered the market
                corneredLikelehood++;
                if (corneredLikelehood == 5) {
                    // probably cornered the market
                    marketCornered = true;
                }
            }
            return maxOffer;
        } else {
            // who needs offers when the market is cornered!?
            return null;
        }
    }

    public Offer makeOffer(List<Stock> currentStock) {
        ticks++;
        if (ticks >= 999) {
            // SELL SELL SELL!
            return new Offer(new Stock(corneredStockType, 1000), 1000);
        } else {
            return null;
        }
    }

    public void secretValue(int stockType, int value) {
        knownStock = stockType;
        knownPrice = value;
        if (stockType == corneredStockType) {
            if (knownPrice == 1000) {
                corneredLikelehood += 3;
            } else if (knownPrice < 900){
                // didn't corner the market.
                corneredLikelehood = 0;
            }
        }
    }
}

"I've cornered the Gold Market, Mr. Bond!"

noɥʇʎԀʎzɐɹƆ

Posted 2016-08-29T21:13:42.407

Reputation: 1 316

I've included an auto-downloader for bots. Please put your code in a code-block. If it won't fit, that's fine. – Nathan Merrill – 2016-08-29T23:45:22.120

@NathanMerrill I understand. But does it compile? – noɥʇʎԀʎzɐɹƆ – 2016-08-29T23:45:54.483

@NathanMerrill done. Probs doesn't compile. interesting strategy, eh? And a lesson in economics! – noɥʇʎԀʎzɐɹƆ – 2016-08-29T23:47:27.157

for (offer: offers) -> for (Offer offer: offers) – Nathan Merrill – 2016-08-30T00:09:48.013

corneredStockType == null is also not valid. an int cannot be null. – MegaTom – 2016-08-30T18:56:29.977

@AgentCrazyPython I fixed the syntax errors for you, you can accept them here (at least, I'm pretty sure you can)

– Socratic Phoenix – 2016-08-30T22:02:26.610

@SocraticPhoenix thanks. I was too lazy to set up my IDE and import all the modules... – noɥʇʎԀʎzɐɹƆ – 2016-08-30T22:29:36.623

This bot is occasionally return an offer with a type of -1. – Nathan Merrill – 2016-09-01T18:27:33.527

2

Spammer, Java

import java.util.List;
import java.util.ArrayList;
import com.ppcg.stockexchange.*;

public class Spammer extends Player {
    private boolean panic = false;

    public Offer acceptOffer(List<Offer> offers) {
        for (Offer offer : offers) {
            if (this.panic || offer.getPayment() < 20)
                return offer;
        }
        return null;
    }
    public Offer makeOffer(List<Stock> currentStock) {
        if (currentStock.size() > 1) { // Don't sell all the stock
            this.panic = false;
            return new Offer(currentStock.get(secretStockType).setAmount(1), 1);
        }
        this.panic = true; // BUY
        return null;
    }
}

Spam the market with really cheap stock, and only buy stock when the price is lesser than 20. When the stock count fall to 1, it will try to buy anything.

TuxCrafting

Posted 2016-08-29T21:13:42.407

Reputation: 4 547

works well in Great Depression – noɥʇʎԀʎzɐɹƆ – 2016-08-30T23:32:03.170

...how is this winning!? – noɥʇʎԀʎzɐɹƆ – 2016-08-30T23:32:31.983

2

WallStreet, Kotlin

Starts by selling high and buying low and gradually shifts to what it thinks the price really is. Also, you can use this as a template for making your own in kotlin.

Note: There is a bug in here that I can't seem to reliably reproduce. If my program crashes or has problems, please ping me in chat and link a pastebin of the contents of submissions/other/WallStreet/log.txt

kotlinc WallStreet.kt
kotlin WallStreetKt
WallStreet.kt
import java.io.FileOutputStream
import java.io.PrintStream
import java.util.*

val LOGGER = PrintStream(FileOutputStream("log.txt", true))
const val DEBUG = false

const val LOG_GAME_HEADER = """
###############
#STARTING GAME#
###############"""

data class Stock(val type : Int, val amount : Int) {

    operator fun minus(amount : Int) = copy(amount = this.amount - amount)
    operator fun plus(amount: Int) = copy(amount = this.amount + amount)
    fun setAmount(amount: Int) = copy(amount = amount)

    operator fun minus(other : Stock) : Stock {
        assert(type == other.type)
        return copy(amount = this.amount - other.amount)
    }

    operator fun plus(other : Stock) : Stock {
        assert(type == other.type)
        return copy(amount = this.amount + other.amount)
    }

    override fun toString() = "$type:$amount"
}

data class Offer(val offer: Stock, val payment: Int) {
    override fun toString() = "$offer@$payment"
}

fun parseStock(repr : String) : Stock {
    val data = repr.split(":").map { it.toInt() }
    return Stock(data[0], data[1])
}

fun parseOffer(repr: String) : Offer {
    val data = repr.split("@")
    return Offer(parseStock(data[0]), data[1].toInt())
}

fun parseOffers(repr: String) = if (repr == "") emptyList<Offer>() else repr.split(";").map { parseOffer(it) }


interface Player {
    fun secretValue(stockType: Int, value: Int)
    fun makeOffer(currentStock: List<Stock>) : Offer?
    fun acceptOffer(offers: List<Offer>) : Offer?
    fun acceptedOffers(offers: List<Offer>)

    var random : Random
}

fun main(args : Array<String>) {

    try {

        if (DEBUG) {
            LOGGER.println(LOG_GAME_HEADER)
        }
        //Change bot name here
        val player = WallStreet()

        while (true) {
            val function = readLine()
            function ?: return
            val line = readLine()!!
            if (DEBUG) {
                LOGGER.println("\nInput:")
                LOGGER.println(function)
                LOGGER.println(line)
            }
            var result : Any
            try {
                result = when (function) {
                    "SecretValue" -> {
                        val data = line.split(":").map { it.toInt() }
                        player.secretValue(data[0], data[1])
                    }
                    "MakeOffer" -> player.makeOffer(line.split(";").map { parseStock(it) }) ?: ""
                    "AcceptOffer" -> player.acceptOffer(parseOffers(line)) ?: ""
                    "AcceptedOffers" -> player.acceptedOffers(parseOffers(line))
                    "RandomSeed" -> player.random = Random(line.toLong())
                    else -> return        //Exit program
                }
                if (function == "AcceptOffer" && result.toString() !in line) {
                    throw Exception("Offer not among available offers!!!!\nResult: $result\nParsed Available Offers: ${parseOffers(line)}")
                }
            } catch (e : Exception) {
                LOGGER.println("Turn #${player.turn}")
                LOGGER.println("\nInput:")
                LOGGER.println(function)
                LOGGER.println(line)
                throw e
            }

            if (result == Unit) {
                result = ""
            }
            if (DEBUG) {
                LOGGER.println("Output:")
                LOGGER.println(result)
            }

            println(if (result == Unit) "" else result)
        }
    } catch (e : Exception) {
        e.printStackTrace(LOGGER)
        throw e
    } finally {
        LOGGER.close()
    }
}


// ###################################################
// #          Put program logic below here.          #
// ###################################################


const val DEFAULT_STOCK_VALUE = 333
const val MAX_TURNS = 1000
const val MAX_STOCK_VALUE = 1000

class WallStreet : Player {

    var secretStockType = 0
    var secretStockValue = 0
    override var random = Random()


    var turn = 0
    val stockPriceStatistics = mutableMapOf<Int, DoubleSummaryStatistics>()

    override fun secretValue(stockType: Int, value: Int) {
        secretStockType = stockType
        secretStockValue = value
    }

    override fun makeOffer(currentStock: List<Stock>): Offer {
        val stock = currentStock[random.nextInt(currentStock.size)]
        val type = stock.type
        val amount = random.nextInt(stock.amount)
        val price = getSellPrice(type) * amount
        return Offer(Stock(type, amount), Math.ceil(price).toInt())
    }

    override fun acceptOffer(offers: List<Offer>): Offer? {
        var bestOffer : Offer? = null
        var mostProfit = 0.0
        for (offer in offers) {
            val offerProfit = profitOfOffer(offer)
            if (offerProfit > mostProfit) {
                bestOffer = offer
                mostProfit = offerProfit
            }
        }
        if (bestOffer != null && bestOffer !in offers) {
            throw IllegalStateException("Tried to accept non-existent offer.\nOffer:  $bestOffer\nAvailable Offers: ${offers.joinToString(";")}")
        }
        return bestOffer
    }

    override fun acceptedOffers(offers: List<Offer>) {
        turn++
        for ((stock, payment) in offers) {
            val stats = stockPriceStatistics.getOrPut(stock.type) { DoubleSummaryStatistics() }
            for (i in 1..stock.amount) {
                stats.accept(payment.toDouble() / stock.amount)
            }
        }
    }

    private fun getSellPrice(type: Int): Double {
        var price = getPrice(type)
        if (price < 1000) {
            price += (1000 - price) * (MAX_TURNS - turn) / MAX_TURNS
        }
        return if (type == secretStockType) Math.max(secretStockValue.toDouble(), price) else price
    }

    private fun getPrice(type: Int): Double {
        return stockPriceStatistics[type]?.average ?: DEFAULT_STOCK_VALUE.toDouble()
    }

    private fun profitOfOffer(offer: Offer): Double {
        return getBuyPrice(offer.offer.type) * offer.offer.amount - offer.payment
    }

    private fun getBuyPrice(type: Int): Double {
        var price = getPrice(type)
        price = price * turn / MAX_TURNS
        return if (type == secretStockType) Math.min(secretStockValue.toDouble(), price) else Math.min(price, MAX_STOCK_VALUE.toDouble())
    }

}

TheNumberOne

Posted 2016-08-29T21:13:42.407

Reputation: 10 855

command.txt doesn't need the file name. Nice post! – Nathan Merrill – 2016-08-30T19:32:14.737

I thought string interpolation was done with ${}, not just $? – Socratic Phoenix – 2016-08-31T01:37:41.810

@SocraticPhoenix $ only works with a variable name. ${} executes arbitrary code. Basically, it works either way and I prefer without the braces. – TheNumberOne – 2016-08-31T03:07:17.743

FYI: as a temporary solution, window users who want to run this file need to change the command.txt: kotlinc->kotlinc.bat and kotlin->kotlin.bat – Nathan Merrill – 2016-08-31T13:14:55.430

Once I fixed my controller, this bot started returning a bunch of bad data, so I removed it from the competition. I can help you in the chat room if you want :) – Nathan Merrill – 2016-09-01T18:37:07.963

2

InsideTrader, Java

InsideTrader just looked around and saw that everybody was trying to be creative. But he did something creative: do what is expected.

This bot buys when it's "worth it" because it "borrowed" some "internal documents" to "guide" "investing decisions".

To-Do and how it works in the code. ;)

The "code"

import java.util.List;

import com.ppcg.stockexchange.*;

public class InsideTrader extends Player {
    public String coverStory = "I can tell the good companies from the bad ones.";
    private String theTruth = "I'm cheating. (but so is everyone else)";
    private String ambitions = "Learn to \"follow the market\"";  // don't steal this idea
    private int secretStock = -1;
    private int secretStockValue = -1;

    private int appraiseOffer(Offer offer) {
        /* get how much the offer is worth, 0 if it's not the secret stock */
        if (offer.getOffer().getType() != secretStock ||offer.getOffer().getAmount() == 0) {
            return 0;
        }
        return (offer.getPayment()/offer.getOffer().getAmount())  // price per stock...
                - secretStockValue  // minus value of stock.
                ;
    }
    public Offer acceptOffer(List<Offer> offers) {
        Offer bestOffer = null;
        int bestOfferValue = -1;
        for (Offer offer :
                offers) {
            int value = appraiseOffer(offer);
            if (value > bestOfferValue && value > 0) {
                bestOfferValue = value;
                bestOffer = offer;
            }
        }
        return bestOffer;
    }

    public Offer makeOffer(List<Stock> currentStock) {
        return new Offer(new Stock(0,1), Integer.MAX_VALUE);
    }

    public void secretValue(int stockType, int value) {
        secretStock = stockType;
        secretStockValue = value;
    }

    public void acceptedOffers(List<Offer> acceptedOffers) {

    }
}

noɥʇʎԀʎzɐɹƆ

Posted 2016-08-29T21:13:42.407

Reputation: 1 316

You can't have those extra classes at the start of the file... it's syntactically invalid... they can be appended to the end without public, i think – Socratic Phoenix – 2016-08-30T23:51:26.353

Error on line 50: modifier private not allowed here Error on line 54: modifier private not allowed here. I'd just remove the classes, and have it extend Player – Nathan Merrill – 2016-08-31T02:06:32.907

Just a note, some new bots are offering stocks at amounts of zero, so your bot is throwing an ArithimeticException (/ by zero) from the return of appraiseOffer... maybe add a check or something? – Socratic Phoenix – 2016-08-31T21:46:57.363

@SocraticPhoenix Thanks, will fix. – noɥʇʎԀʎzɐɹƆ – 2016-08-31T23:28:36.313

Congrats, this bot is currently in second! – Nathan Merrill – 2016-09-01T18:31:12.277

2

DartMonkey, Java

(non-competing: It won't win and I already have another answer)

Dart monkey likes throwing things... and there's a big pile of pointy sticks next to him. He sees some paper on the wall. Bam! Bam! Bam! In no time at all, Dart Monkey's thrown 80 darts! Half the darts are red, and the other half are blue, and there's random numbers on them! Dart monkey sees a computer... dart monkey types in the numbers. Dart monkey likes numbers. Dart monkey makes some money from his darts...


In all seriousness, DartMonkey initializes an integer array that has a length that is twice the number of stocks. He stores one number for the amount of stock he wants to buy/sell, and one number for the price of the stock. He then alternates selling stock from the array, and accepting offers according to the array. If he has no stock from the array, he won't offer anything, and if he has no offers given to him from the array, he won't accept anything.


This answer was inspired by @TheNumberOne, who mentioned dart monkeys in the chat

import com.ppcg.stockexchange.Offer;
import com.ppcg.stockexchange.Player;
import com.ppcg.stockexchange.Stock;

import java.util.List;
import java.util.Random;

public class DartMonkey extends Player {
    private int basePrice = 100;
    private int numStocks;
    private int[] dartBoard;
    private boolean first = true;

    @Override
    public Offer acceptOffer(List<Offer> offers) {
        for(Offer offer : offers) {
            Stock stock = offer.getOffer();
            int type = stock.getType();
            int amount = stock.getAmount();
            int price = offer.getPayment();
            if(this.dartBoard[type] < 0 && amount <= -this.dartBoard[type] && price <= this.dartBoard[type + this.numStocks]) {
                this.dartBoard[type] = 0;
                return offer;
            }
        }
        return null;
    }

    @Override
    public Offer makeOffer(List<Stock> stocks) {
        if(this.first) {
            this.first = false;
            this.numStocks = stocks.size();
            this.dartBoard = new int[this.numStocks * 2];
            Random random = this.getRandom();
            for (int i = 0; i < 20; i++) {
                int index = random.nextInt(this.dartBoard.length / 2);
                this.dartBoard[index] = random.nextInt(1001);
                this.dartBoard[this.numStocks + index] = random.nextInt(1001);
            }

            for (int i = 0; i < 20; i++) {
                int index = random.nextInt(this.dartBoard.length / 2);
                this.dartBoard[index] = -random.nextInt(1001);
                this.dartBoard[this.numStocks + index] = random.nextInt(1001);                
            }
        }

        for (Stock stock : stocks) {
            int type = stock.getType();
            if(this.dartBoard[type] > 0) {
                Offer offer = new Offer(stock.setAmount(this.dartBoard[type]), this.basePrice + this.dartBoard[type + this.numStocks]);
                this.dartBoard[type] = 0;
                this.dartBoard[type + this.numStocks] = 0;
                return offer;
            }
        }

        return null;
    }

}

Socratic Phoenix

Posted 2016-08-29T21:13:42.407

Reputation: 1 629

I see you have went on a random walk down wall street? – Rohan Jhunjhunwala – 2016-08-31T22:30:25.063

This is arguably a suicidal entry, which are not allowed.

– Mego – 2016-09-02T04:23:43.573

1@Mego I don't see how... A suicidal entry would sell stock for 0 dollars, this entry determines what it buys and sells randomly. Which is definitely not against the rules.... – Socratic Phoenix – 2016-09-02T09:40:23.870

1

UncleScrooge, Java

import java.util.List;
import com.ppcg.stockexchange.*;

public class UncleScrooge extends Player {
    public Offer acceptOffer(List<Offer> offers) {
        Offer offer;
        try {
            offer = offers.get(0);
        } catch (Exception ex) {
            return null;
        }
        if (offer.getPayment() < 100)
            return offer;
        else
            return null;
    }
    public Offer makeOffer(List<Stock> currentStock){
        if (this.getRandom().nextDouble() < 0.6)
            return new Offer(currentStock.get(secretStockType).setAmount(1), Integer.MAX_VALUE);
        else
            return null;
    }
    public void secretValue(int stockType, int value) {
        super.secretValue(stockType, value);
    }
    public void acceptedOffers(List<Offer> acceptedOffers) { }
}

Sell stock at a really high price, and only buy if the price is less than 100.

TuxCrafting

Posted 2016-08-29T21:13:42.407

Reputation: 4 547

1

Profiteer, Java

Profiteer is in it for the money, and he's always counting coins. He makes a conservative estimate of how much money he's got. He'll then buy the secret stock, if it's less than the value, or buy cheap stock. He also remembers how much he's paid for everything, and always makes offers above the stock price. Furthermore, he'll make higher offers if he has less money.

Note: I think I've done this correctly, but if @NathanMerrill wouldn't mind skimming my code for bugs, that'd be great

import com.ppcg.stockexchange.Offer;
import com.ppcg.stockexchange.Player;
import com.ppcg.stockexchange.Stock;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

public class Profiteer extends Player {
    private List<StockInfo> onMarket;
    private List<StockInfo> stocks;
    private int money;
    private boolean first = true;

    @Override
    public Offer acceptOffer(List<Offer> offers) {
        Offer finalOffer;

        Optional<Offer> offer = offers.stream().filter(o -> o.getOffer().getType() == this.secretStockType && o.getPayment() < this.secretStockValue * o.getOffer().getAmount()).sorted((a, b) -> Integer.compare((this.secretStockValue * a.getOffer().getAmount()) - b.getPayment(), (this.secretStockValue * b.getOffer().getAmount()) - b.getPayment())).findFirst();
        if (offer.isPresent()) {
            finalOffer = offer.get();
        } else {
            finalOffer = offers.stream().sorted((a, b) -> Integer.compare(a.getPayment(), b.getPayment())).findFirst().orElse(null);
        }

        if (finalOffer == null || this.money <= finalOffer.getPayment()) {
            return null;
        } else {
            this.stocks.add(new StockInfo(finalOffer.getOffer(), finalOffer.getPayment()));
            this.refreshMoney();
            return finalOffer;
        }
    }

    @Override
    public Offer makeOffer(List<Stock> stocks) {
        if (this.first) {
            this.init(stocks);
        } else {
            this.refreshMarketList(stocks);
        }

        Optional<StockInfo> least = this.stocks.stream().sorted((a, b) -> Integer.compare(a.getBoughtPrice(), b.getBoughtPrice())).findFirst();
        Optional<StockInfo> secret = this.stocks.stream().filter(stockInfo -> stockInfo.getStock().getType() == this.secretStockType).sorted((a, b) -> Integer.compare(a.getBoughtPrice(), b.getBoughtPrice())).findFirst();

        StockInfo finalOffer;
        int price;
        if (secret.isPresent()) {
            finalOffer = secret.get();
        } else if (least.isPresent()) {
            finalOffer = least.get();
        } else {
            return null;
        }

        this.onMarket.add(finalOffer);
        this.stocks.remove(finalOffer);
        price = this.calculatePrice(finalOffer.boughtPrice);
        return new Offer(new Stock(finalOffer.getStock().getType(), finalOffer.getStock().getAmount()), price);
    }

    private int calculatePrice(int boughtPrice) {
        return (int) (boughtPrice + ((boughtPrice / (double) this.money) * this.money)) + 1;
    }

    private void refreshMarketList(List<Stock> stocks) {
        this.stocks.addAll(this.onMarket.stream().filter(stockInfo -> stocks.contains(stockInfo.getStock())).collect(Collectors.toList()));
        this.onMarket.clear();
    }

    private void refreshMoney() {
        this.money = this.stocks.stream().mapToInt(info -> this.secretStockType == info.getStock().getType() ? this.secretStockValue : 5).reduce((a, b) -> a + b).orElseGet(() -> 0) - this.stocks.stream().mapToInt(StockInfo::getBoughtPrice).reduce((a, b) -> a + b).orElseGet(() -> 0);
    }

    private void init(List<Stock> stocks) {
        this.stocks = stocks.stream().map(stock -> new StockInfo(stock, 0)).collect(Collectors.toList());
        this.onMarket = new ArrayList<>();
        this.money = 0;
        this.first = false;
        this.refreshMoney();
    }

    private static class StockInfo {
        private Stock stock;
        private int boughtPrice;

        public StockInfo(Stock stock, int boughtPrice) {
            this.stock = stock;
            this.boughtPrice = boughtPrice;
        }

        public Stock getStock() {
            return this.stock;
        }

        public int getBoughtPrice() {
            return this.boughtPrice;
        }

    }

}

Socratic Phoenix

Posted 2016-08-29T21:13:42.407

Reputation: 1 629

you can go into debt and still by stocks... – noɥʇʎԀʎzɐɹƆ – 2016-08-30T21:28:41.320

@AgentCrazyPython I know, but profiteer doesn't want to risk it – Socratic Phoenix – 2016-08-30T21:32:59.187

can't undownvote – noɥʇʎԀʎzɐɹƆ – 2016-08-30T23:36:30.320

@AgentCrazyPython meh, it's okay, the game is fun and that's what matters – Socratic Phoenix – 2016-08-30T23:48:11.057

1

MaxBot, Java

This bot tries to make the most profit out of each transaction. While selling, puts the price of an unknown stock at $300, when buying $250.

import java.util.List;
import com.ppcg.stockexchange.*;
public class MaxBot extends Player {
    int toSell;
    int sellPrice;

    public void secretValue(int stockType, int value) {
        super.secretValue(stockType, value);
        toSell = stockType;
        sellPrice = (value + 1000)/2;
    }
    public Offer acceptOffer(List<Offer> offers) {
        Offer max = null;
        int maxDif = 0;
        for(Offer o: offers){
            int price = secretStockType == o.getOffer().getType()? secretStockValue: 250;
            int val = price * o.getOffer().getAmount();
            int dif = val - o.getPayment();
            if(maxDif < dif){
                max = o;
                maxDif = dif;
            }
        }
        return max;
    }
    public Offer makeOffer(List<Stock> currentStock){
        if(toSell == -1){
            return null;
        }
        int sum = 0;
        for (Stock s: currentStock){
            if(s.getType() == toSell){
                sum += s.getAmount;
            }
        }
        int n = sum - sum/2;
        return new Offer(new Stock(toSell, n), n * sellPrice);
    }
    public void acceptedOffers(List<Offer> acceptedOffers) {
        int highStock = -1;
        int highPrice = 0;
        int markup = 0;
        for(Offer o: offers){
            int trueVal = secretStockType == o.getOffer().getType()? secretStockValue: 250;
            int marketVal = o.getPayment()/o.getOffer().getAmount();
            if(marketVal - trueVal > markup){
                highStock = o.getOffer().getType();
                highPrice = marketVal;
                markup = marketVal - trueVal;
            }
        }
        toSell = highStock;
    }
}

MegaTom

Posted 2016-08-29T21:13:42.407

Reputation: 3 787

1

BlackMarket, Java

Not much to say about this one, seeing as these transactions will be... off the charts, you might say.

import java.util.List;
import com.ppcg.stockexchange.*;

public class BlackMarket extends Player {
    private boolean approvedBySEC = false;
    private int ammoLeft = 30;
    public String taxView = "We want higher tax rates";
    public String excuse = "I never saw that in my life";

    public void secretValue(int drugType, int warrantForMyArrest) {
        super.secretValue(drugType, warrantForMyArrest);
        if (warrantForMyArrest != 0 || drugType == 420) {
            ammoLeft += 10;
        }
    }

    public Offer acceptOffer(List<Offer> offers) {
        for (Offer offer : offers) {
            if (this.approvedBySEC || offer.getPayment() < 9)
                return offer;
        }
        return null;
    }


    public Offer makeOffer(List<Stock> currentStock) {
        return new Offer(new Stock(0,1),420);
    }
}

Timtech

Posted 2016-08-29T21:13:42.407

Reputation: 12 038

return null is outside... please indent properly too. – noɥʇʎԀʎzɐɹƆ – 2016-08-31T20:37:17.057

1@AgentCrazyPython Thanks! We'll retrieve the "return null" as soon as it's dark. Be wary of cars following you for the next month. – Timtech – 2016-08-31T21:01:04.160

1Why the downvote? We placed fourth in the last competition. Although we're not exactly sure how... – Timtech – 2016-09-02T16:16:15.610

0

NotQuiteABanksBestFriend, Python 3

Command.txt:

python3 NotQuiteABanksBestFriend.py
NotQuiteABanksBestFriend.py
import random
from functools import total_ordering
from io import StringIO

log = StringIO()
log.write("\n\n~~~NEW GAME~~~\n\n")

LIST_DELIMITER = ';'
STOCK_DELIMITER = ':'
OFFER_DELIMITER = '@'

JAVA_MAX_INT = 2147483647

@total_ordering
class Stock:
    @staticmethod
    def parse(string: str):
        return Stock(*map(int, string.split(STOCK_DELIMITER)))

    def __init__(self, stock_type: int, amount: int):
        self.type = stock_type
        self.amount = max(amount, 0)

    def __str__(self):
        return "T%sx%s"%(self.type, self.amount)

    def __repr__(self):
        return str(self.type)+STOCK_DELIMITER+str(int(self.amount))

    def __bool__(self):
        return bool(self.amount)

    def __eq__(self, other):
        return self.amount == other.amount

    def __lt__(self, other):
        return self.amount < other.amount

    def update(self, amount) -> 'Stock':
        return Stock(self.type, amount)

    def __mul__(self, other: int) -> 'Stock':
        return self.update(self.amount*other)

    def __floordiv__(self, other: int) -> 'Stock':
        return self.update(self.amount//other)

    def __add__(self, other: int) -> 'Stock':
        return self.update(self.amount+other)

    def __sub__(self, other: int) -> 'Stock':
        return self.update(self.amount-other)


class Offer:
    @staticmethod
    def parse(string: str) -> 'Offer':
        try:
            stock, price = string.split(OFFER_DELIMITER)
        except ValueError:
            raise Exception("Cannot unpack "+string)
        return Offer(Stock.parse(stock), int(price.strip()))

    def __init__(self, stock: Stock, price: int):
        self.stock = stock
        self.price = price
        try:
            self.price_per_unit = self.price/self.stock.amount
        except ZeroDivisionError:
            self.price_per_unit = float('inf')

    def __str__(self):
        return "%s$%s"%(self.stock, self.price)

    def __repr__(self):
        return repr(self.stock)+OFFER_DELIMITER+str(int(self.price))


def read_stock_value(value: str):
    global hidden_price, hidden_stock
    stock, price = value.split(STOCK_DELIMITER)
    hidden_price = float(price)
    hidden_stock = int(stock)
    log.write("Hidden StockID: %s\nHidden Price: %s\n"%(hidden_stock, hidden_price))

def process_input():
    handlers = {
        "SecretValue": read_stock_value,
        "RandomSeed": read_seed,
        "MakeOffer": make_offer,
        "AcceptOffer": accept_offer,
        "AcceptedOffers": accepted_offers,
    }
    method = input().strip()
    data = input().strip()
    output = handlers[method](data)
    if output is not None:
        print(repr(output))
    else:
        print()

def read_seed(seed: str):
    random.seed(int(seed))

def start():
    while True:
        process_input()

hidden_stock = None
hidden_price = None

def filter_offers(offer):
    if offer.stock.amount == 0:
        return False
    if offer.price_per_unit > 1000:
        return False
    return True

def certain_profit(offer):
    stock = offer.stock
    if stock.type == hidden_stock and offer.price_per_unit < hidden_price:
        log.write("Offer, %s is certainly profitable.\n"%offer)
        return True
    return False

def make_offer(current_stock: str):
    current_stock = list(map(Stock.parse, current_stock.split(LIST_DELIMITER)))
    own_stock = [stock for stock in current_stock if stock.type == hidden_stock]
    if own_stock and own_stock[0]:
        own_stock = own_stock[0]
        amount_sold = min(random.randrange(1,50), own_stock.amount)
        price = hidden_price+random.randrange(10,50)
        return Offer(Stock(hidden_stock, amount_sold), price*amount_sold)
    sell_stock = random.choice(current_stock)
    amount_sold = min(random.randrange(1,50), sell_stock.amount)
    price = random.randrange(1000, JAVA_MAX_INT//(amount_sold or 1))
    return Offer(Stock(sell_stock.type, amount_sold), price*(amount_sold or 1))

def accept_offer(available_offers: str):
    available_offers = list(map(Offer.parse, available_offers.split(LIST_DELIMITER)))
    filtered_offers = list(filter(filter_offers, available_offers))
    profitable = list(filter(certain_profit, filtered_offers))
    rtn_list = filtered_offers
    if profitable:
        log.write("Profitable: %s\n"%profitable)
        rtn_list = profitable
    if not rtn_list:
        return None
    accepted_offer = min(rtn_list, key=lambda offer: offer.price_per_unit)
    log.write("Bidded for %s\n"%accepted_offer)
    return accepted_offer

def accepted_offers(offers: str):
    pass


if __name__ == "__main__":
    try:
        start()
    finally:
        log.close()

Always tries to sell hidden stock for more than it's worth.

Blue

Posted 2016-08-29T21:13:42.407

Reputation: 26 661