"Useful" self-modifying script for financial firm

7

1

True Story: Several years ago while interviewing at an investment advisory firm that managed over a billion dollars in client funds, I was asked a collection of reasonable and bizarre questions by a partner in the firm. An example of a reasonable question would be "What can go wrong with a linear fit?".

But then, things devolved....

Interviewer: "Have you ever written code that modifies itself?"

Job Candidate: "No, can't say that I have"

Interviewer: "We have one guy who writes programs that modify themselves, I think he uses awk"

Job Candidate: "Wow. That's pretty incredible. AWK? "

Now it is your turn to be that one guy that financial houses would kill to hire...

Challenge: Write a self-modifying script of some kind that performs a "useful financial function".

Rules:

  1. Use a scripting language, not a language requiring compilation such as C or Java. Perl, Python and the like that will work from a #! are OK. Of course, heroes use awk, but awk is not a requirement.
  2. Self-modifying means that the script modifies its own source code. The script must be reusable after it has modified itself. The script might also generate useful user output to STDOUT or some other interface.
  3. The definition of "useful financial function" is left to the voters and can be as intriguing or dysfunctional as you prefer. If you need examples for inspiration, here are a few ideas: stock picking, stock trading, prediction and/or fitting, future value of account, Ponzi scheme generator, risk analysis of Nigerian email deals, salary bonus calculator for partners vs employees, etc.
  4. Most upvotes wins.

EDIT: I agree with one participant who notes that it is not obvious how to read the current gawk script from within gawk. Here is a solution for Linux-based systems and other O/S that have a /proc filesystem.

#!/usr/bin/gawk -f
BEGIN { 
pid = PROCINFO["pid"]
commfile = "/proc/"pid"/comm"
print "I will look here for the script file name: " commfile
print "Here is what is in that file:"
getline scriptfilename < commfile
print scriptfilename
print "Here is my script:"
while (getline line < scriptfilename){
      print line
      }
}

Paul

Posted 2013-12-30T11:22:13.163

Reputation: 357

Question was closed 2017-08-03T19:23:05.730

Removed code-challenge tag because it would require an objective winning criterion. – Howard – 2013-12-30T12:27:22.600

Wait, rule 2 disallows the self-modify Befunge. :-( – Justin – 2013-12-30T16:58:23.723

@Quincunx How would you modify the rule? – Paul – 2013-12-30T20:04:26.477

@Paul I'd just say that the program must be self-modifying: edits its own source code. – Justin – 2013-12-31T00:57:23.180

@Quincunx Sounds like a fine idea. – Paul – 2013-12-31T09:13:48.230

Wow, I tried to do this in AWK. I gave up after I found out that AWK doesn't support reading the current program. https://gist.github.com/xfix/8201410 - I checked every single variable - nope.

– Konrad Borowski – 2013-12-31T19:49:39.447

@GlitchMr My personal preference is to use awk for short data transformation scripts involving STDIN and STDOUT that are trivial enough not to need perl or python. I can't imagine anyone in their right mind writing a serious application in awk for production use that needs to open/close various files or goes beyond minor data munging or calculation in a pipe. – Paul – 2014-01-01T09:24:39.727

@Paul: I agree, but it was somewhat annoying to find out that after writing everything else in the program. – Konrad Borowski – 2014-01-01T09:41:03.703

@GlitchMr I found a way. – Paul – 2014-01-01T09:51:51.103

You'd need to dig out the pid with gawk's PROCINFO["pid"] and then use that (on Linux) to read the file /proc/(pid)/comm, which has the filename (but not the full path) of the script in it. One could be lazy at this point and assume the script is in the current directory, or read some more PROCINFO and ENV vars and /proc filesystem entries until that is pinned down too. – Paul – 2014-01-01T09:52:55.983

Hm, ok. That would require me to access /proc filesystem that doesn't have to exist (it doesn't exist on FreeBSD I use), but that could work. – Konrad Borowski – 2014-01-01T10:13:25.710

1In PERL, special variable $0 contains the full pathname to the running script. Just goes to show you shouldn't bring gawk to a perl fight. – Paul – 2014-01-01T10:19:27.183

1What! You disallow Java eh! Well, I'm going to write a self modifying Java program, complete with compilation. Challenge accepted. – Justin – 2014-01-22T04:30:53.527

Question: Are we allowed to write our own CPU architecture to run this on, because I have the ISA/Specs. for a computer that I designed where self-modification of programming code is frequent/necessary for small code. Down with Harvard architectures, Up with Von Neumann Architectures! Long live the Princeton Architecture! So, I can't see a problem with it, as assembly is technically interpreted by the machine... – Stack Tracer – 2014-03-19T02:38:01.567

Answers

8

Pseudocode

// Set up a cron job to run this script (only) once a day

yesterdays_stock_price = '46.48'

todays_stock_price = curl_google_finance('VTSMX')

print "Difference between yesterday's stock price and today's: "

print todays_stock_price

self = open('self.file')

self.replace( /yesterdays_stock_price = '[0-9\.]+'/, todays_stock_price)

self.save()

jawns317

Posted 2013-12-30T11:22:13.163

Reputation: 1 132

1Nice. I like how it doesn't work if you use it too much or at the wrong interval. – Paul – 2013-12-30T20:03:50.443

Maybe it should have a wait and loop in it too so it can self run, I love it. – alan2here – 2014-01-02T01:37:18.383

Funny how you call it pseudocode where it's actually nearly Python. – Turion – 2014-03-19T16:26:31.293

3

gawk (1224 characters, as this is not code golf)

One of reasons why awk shouldn't be used for self-modifying scripts.

#!/usr/bin/gawk -f
function download(name,     url, service, host, old_rs, old_ors) {
    old_rs = RS
    old_ors = ORS
    RS = ORS = "\r\n"

    host = "download.finance.yahoo.com"
    url = "http://"host"/d/quotes.csv?s="name"&f=l1"
    service = "/inet/tcp/0/"host"/80"
    print "GET", url |& service
    service |& getline
    close(service)

    RS = old_rs
    ORS = old_ors

    return $0
}

function update(value,       file, self, result) {
    # Do complex stuff in order to find the program itself.
    file = "/proc/"PROCINFO["pid"]"/comm"
    if (getline < file <= 0) {
        print "/proc filesystem not supported." > "/dev/stderr"
        exit
    }
    close(file)
    if ($0 ~ /^g?awk$/) {
        print "You need to run program directly." > "/dev/stderr"
        exit
    }
    self = $0
    result = ""
    while (getline < self > 0) {
        # Avoid finding this line.
        if (/[y]esterday/) gsub(/[0-9]+(\.[0-9]+)?/, value)
        result = result $0"\n"
    }
    printf "%s", result > self
    close(self)
}

BEGIN {
    yesterday = 1120.71
    today = download("GOOG")
    update(today)
    print "Yesterday:", yesterday
    print "Today:", today
    print "Difference:", today - yesterday
}

Konrad Borowski

Posted 2013-12-30T11:22:13.163

Reputation: 11 185

Wow, an HTTP client in GAWK. – Paul – 2014-01-01T10:31:59.603

2

Using @jawns317 psueudocode:

BASH

#!/bin/bash
set -e;
google_price_last=1118.79;
current_google_price=`wget -qO- "http://finance.yahoo.com/d/quotes.csv?s=GOOG&f=l1"|tr -d "\r\n"`;
echo "Current Price: $current_google_price";
echo "Last Price: $google_price_last";
echo "Price change: "`echo $current_google_price - $google_price_last | bc -l`;
sed -ri 's/last=[0-9\.]+\;/last='"$current_google_price"';/g' $0;

Tyzoid

Posted 2013-12-30T11:22:13.163

Reputation: 692

1

Back at uni I discovered (ah-hem) a system which I though would prove fool-proof at the local casino. Bet on red on the roulette wheel, and if you lost double the bet, and so on ...See Martingale System

VBS

Dim objFSO
Dim objTF
Dim strFile
Dim lngBet

lngBet = 5
strFile = "boss.txt"
'spin roulette wheel
Randomize

'18 blacks, 18 reds, 1 green    
intnumber = Int(36 * Rnd + 1)

'mofify code to double-down losing bets
Do While intnumber < 18 
intnumber = Int(36 * Rnd + 1)
bfound = True
Set objFSO = CreateObject("scripting.filesystemobject")
Set objTF = objFSO.createtextfile(strFile, 2)
objTF.writeline "lngbet=lngbet*2"
objTF.Close
Set objTF = objFSO.opentextfile(strFile, 1)
Execute objTF.ReadAll()
objTF.Close
Loop

If bfound Then objFSO.deletefile (strFile)    
wscript.echo "final bet was " & lngBet

brettdj

Posted 2013-12-30T11:22:13.163

Reputation: 129

0

I have some pseudo code for someone to develop. All it really needs are some functions built to do the text replacement. I feel the function names give a sufficient description that the actual code is probably trivial.

Write "You should really give him back his stapler."
Write "No one has noticed an account with $0 ."
Write "Your TPS reports are complete."
Write "You should throw that Piece of * out the window."

$event = Random 1..3
$fireStarter = Random 1..100
$fractions = Random 1..100

switch $event
    {
    1 - $stapler = $false
    2 - $TPSreports = $false
    3 - $printerJam = $true
    }

if ($stapler = false)
    { Write "I think you have my stapler"

           if ( ($times + $fireStarter ) -GreaterThan 100 ) { Function Burn }
    $times + 1
    $stapler = $true
    Function SelfModifyLine1
    Function SelfModifyTimes
    }

if ( $Fractions -LessThan 50 )
    { $account = $account + $fractions 
    Function SelfModifyLine2 }

if ( $TPSreports = $false ) {  Function SelfModifyLine3  }

Function YellAtPrinter
Out-file $scriptPath

H.R.Rambler

Posted 2013-12-30T11:22:13.163

Reputation: 331