Scripting Commands and Python API

Batch Commands

StockWave can be controlled by entering commands into its shell interpreter. There is an example script for StockWave called "example.script" and is located in the /scripts directory. All of these calls have Python equivalents, the operation of which is detailed in the next section. With these commands you can automate many tasks you would normally complete by using the GUI directly, clicking the mouse and so on, thus common sequences of tasks can be speeded up by creating small programs known as scripts. This feature when extended into the Python language will allow automated traders and strategy builders to make their own trading systems which incorporate StockWave's advanced features.

Configuration

autoarrange

Will place the principal form windows on the screen in a pleasant and uncluttered manner. Useful when you have been doing a lot of things and it's getting a bit confusing, even with multiple monitors.

set region regionID 

where

regionID : = US | UK | EU | AUS | IND

we can query for basic information -

get region
get version
get license
get user
list markets
list stocks groupID

where

groupID : = ftse100 | ftse250 | ftseaim | asx100 | dow | nas100 | nse500 | eu50 
list

on its own is a very useful command as it will tell you all the active objects and windows you have created in your interactive session. The first thing you are likely to want to do with StockWave is to start reading data. Streaming datacapture and configuration is dealt with in the DataReader form, but there are naturally also script commands to accomplish this.

Data Capture

show datareader

hide datareader

start pricecapture 

start newscapture  

stop pricecapture  

stop newscapture   

start datacapture

stop datacapture

list price sources

list news sources

- the above should be reasonably self-explanatory.

load datasource [filename]

the square brackets indicate an optional argument; if present StockWave will load any datasources contained in the file, if not StockWave will load the default datasources file. These files are in a readable text / markup format which can be hand-edited if necessary.

clear datasource [i]

create price source url arg preprocess frequency 

create news source url frequency

Charting

StockWave was designed so that most of the analytical work was done from the position of viewing a chart of the share price as we consider this to be the most principally important way of looking at things, both literally and metaphorically. Some example commands -

ch1 = open chart abf.lse 

move chart ch1 10 20 400 300 

zoom chart ch1 19 aug 2002 0900 21 oct 2007 1040 

- the purpose of which should be obvious by now; in the first case "abf.lse" is the identifier of the stock we want to chart; in the "move" example the arguments are left top right and bottom; and in the last we have to specify the two positions in time we wish to look at. Note the date-time format as it will be the one used throughout StockWave i.e. dd mmm yyyy 24hr - we choose this as though slightly verbose it is unambiguous and since it is the only format used it diminishes any possible confusion. The time is understood to be in GMT.

The syntax of the first example needs a little explaining - we have created a chart and given it a name, in this case "ch1" - this is rememberd by the system and can be used further on in our work; note that the "list" command will tell use everything that is on the system. Thus we can call -

show ch1

hide ch1

close ch1

and furthermore control the chart annotations -

show news ch1

show events ch1

will add news and news event overlays; the opening chart and adding news annotations can be done in a single command, thus

ch2 = open news chart abf.lse

Printing is also supported.

print chart ch3

Classical Technical Analysis

Classic technical analysis (TA) is also supported, but presented separately in an appropriately named "ta chart" which has a similar interface to the normal charts. Conventional TA is dealt with separately in StockWave as it is not generally speaking part of the main philosophy being used, thus it is presented as a sideline, for those who wish to retain a familiar "crutch".

tach1 = open ta chart abf.lse

move chart tach1 10 20 400 300 

zoom chart tach1 19 aug 2002 0900 21 oct 2007 1040 

we have control over the types of indicators we can draw

show indicator tach1 ma20

hide indicator tach1 ma20

Indicators are ma, ema, boll, psar, macd, w%r, rsi - the ma and ema have a suffix showing the measuring length, e.g. ma20 is a 20 day moving average. psar is the parabolic sar. macd is moving average crossover divergence. rsi is the relative strength indicator and stoch is the stochastic indicator. We may also create standalone indicators for later usage in our model building.

i1 = create indicator abf.lse macd

The user's trading interests are stored in his portfolio - we have a full set of access commands for this.

Portfolio

show portfolio

hide portfolio

delete portfolio

list portfolio

create portfolio bob bob@somedomain.com

select portfolio bob

show closed trades bob

show open position bob

get trades bob

get trade detail tradeID

current position bob

profit closed trades bob

get balance bob brokerID

set broker bob IB

list brokers bob

get default broker bob

The naming convention should be obvious by now, in the above case "bob" is the name of our portfolio.

The following check what trades we can execute on our brokerage account. Note that direct broker support is not available yet, but we expect it to be made available soon.

can trade AAPL

has CFD APPL

has sbet APPL

has options APPL
email bob "AAPL has tanked" c:/temp/appl.gif

The first step in analyzing price data is to select some - we do this by creating a DataSelection object.

Data Selection

ds1 = select data abf.lse 19 aug 2006 0900 21 oct 2007 1040 2hr 

ds0 = select data iii.lse 1 jun 2010 0900 3 sep 2010 1630 1hr

ds3 = select data iii.lse 21 aug 2009 0900 21 aug 2010 1040 4hr

ds4 = select data c.nys   21 aug 2009 0900 21 aug 2010 1040 2hr

The time resolution is the last parameter, which can be

day 4hr 2hr 1hr 30min 20min 15min 10min 5min 3min 1min 30sec 20sec 10sec 5sec 1sec

Optional filtering and threshold parameters can be added.

Signal Processing

We can process the select price data, "cleaning it up" for use later on when we apply our machine learning algorithms.

fw1 = open filterwindow ds1
 
set filter fw1 dau4 0.005

show fw1

hide fw1

ds5 = select data filter ds1 dau4 0.04 

fd1 = get filtered data fw1 

show histogram ds5 50

get volatility ds5

Analyzers

Creating an analyzer is the basic activity in StockWave - these are 2 dimensional probability diagrams which when sliced vertically give the probability distribution of the share price at a given future time; the critical observation is that this is precisely the information you need to make an intelligent trading decision. The basic technique we are using is that of Monte Carlo simulation, a sampling technique which performs many "random walks" to generate a probability; there are also other more intricate algorithms placed on top of this.

Some examples, note that we always give our analyzers a name so we can use them later on, and the basic format is "create analyzer" followed by a list of parameter values appropriate to the algorithm we are using. Some examples -

an1 = create analyzer rw ds1 10000 50 yes        

The parameters indicate, in order -

rw     is the algorithm type 
ds1    is the name of the data selection we are using 
10000  is the number of monte carlo runs 
50     is the number of bins in the histogram
yes    means we are detrending the input data
an2 = create analyzer bcor ds1  5000  13   50  6  cmm  150  0.27

The parameters indicate, in order -

bcor   is the bayesian correlation pattern analyzer algorithm                  
ds1    is the data selection
5000   is the number of runs
13     is discretisation level
50     is the maximum pattern depth
6      is the maximum forward look
cmm    is pattern metric
150    is the neighbourhood size
0.27   is the maximum similarity distance

Don't worry about the meaning of these parameters, or their default values - all will become clear in time. In practice you will be exploring this yourself.

The remaining analyzers are based on different types of neural network architectures, the main types being multilayer feedforward, recurrent and self organising maps.

an3 = create analyzer bpn ds1 10000 100 50 60 150  1.0 0.5  0.05 1.0  5

bpn    is the backpropagation network                   
ds1    is the data selection ID
10000  is the number of runs
100    is number of passes
50     is number of bins
60     is the input length
150    is the number of hidden nodes  
1.0    is bias
0.05   is the learn rate  
1.0    is the sigmoid 
5      is the number of epochs 
an4 = create analyzer rnn ds1 10000 100 50 60 150  1.0 0.5  0.05 1.0  5

rnn    is recurrent network                    
dsID   is data selection ID
NRUN   is the number of runs
NP     is the number of passes
NI     is number of inputs
NH     is the number of hiddens
B      is bias
MF   
LR     is the learn rate   
SG     is the sigmoid gain 
NE     is the number of epochs

// som dsID NRUN  NI NKR NKC SLR SF NTR [pflID filter threshold]
an5 = create analyzer som ds1 10000 40 150 150 0.05 0.05  5

som    is the kohonen self organising map                  
dsID   is data selection ID
NRUN   is the number of runs
NI     is the number inputs
NKR    is the number of koho rows
NKC    is num koho cols
SLR    is
SF     is
NTR    is

is completed an1

- lets you check whether it is ready to be used.

Once you have an analyzer, you can trade on it.

Trading

We can create all the main trade types, the basic format is "create trade" followed by the parameters depending on the trade type. Complex combination trades can also be constructed.

tr1 = create trade iii.lse stock buy 266.00 266.50 500 

stockID    is what we are trading	  
stock      is the trade type, a stocktrade  
buy/sell   is the trade action; long or short
bid        is bid price
offer      is offer price
num        is the number of shares
// [pflID fr pc sd exp sl pt]
        
tr2 = create trade abf.lse cfd buy bid offer
stockID cfd   buy bid offer num [pflID fr pc sd exp sl pt]
tr2 = create trade iii.lse cfd sell 266.05 266.15 1000

stockID    is what we are trading	  
cfd        is the trade type, a contract for difference  
buy/sell   is the trade action; long or short
bid        is bid price
offer      is offer price
num        is the number of shares
// [pflID fr pc sd exp sl pt]

tr3 = create trade abf.lse sbet sell bid offer
stockID spreadbet buy bid offer stake [pflID fr pc sd exp sl pt]
tr3 = create trade iii.lse sbet sell 266.00 266.20 10

stockID    is what we are trading	  
sbet       is the trade type, a spreadbet  
buy/sell   is the trade action; long or short
bid        is bid price
offer      is offer price
num        is the number of shares
// [pflID fr pc sd exp sl pt]

tr4 = create trade abf.lse call strike exp buy bid offer
stockID call/put strike exp buy/sell bid offer num [pflID fr  pc sd exp   sl pt ]
tr4 = create trade iii.lse call 260 sep/2010 buy 6.99 14.49 1
//tr5 = create trade abf.lse put strike exp buy bid offer
tr5 = create trade iii.lse put 280 sep/2010 buy 10.06 20.56 5

stockID    is the underlying we are trading on 
call/put   is the type of option 
strike     is the strike price of the option
exp        is the expiry date
buy/sell   action
bid        bid price of the option (NOT the underlying)
offer      offer price of the option (NOT the underlying)
num        number of contracts
[pflID fr  pc sd exp   sl pt ]

exp = mmm/yyyy

Once you have made a trade the next thing you want to ask is "is it any good?" which is accomplished by using the analyzer you created previously; remember the analyzer is our mathematical model, our best guess, about what will happen in the future, in this case allowing us to ask "what are the chances of us making money, losing it, and how much?". To this end we take our analyzer and our trade and examine their performance on the Trade Creator form. A small note about terminology, we create a trade for analysis purposes, but that does not mean we have "opened" or executed it - that is a decision to be made later on.

Trade Creator

tc1 = open tradecreator 

set analyzer tc1 an1 

clear analyzer tc1

set trade tc1 tr1

add trade tc1 tr2 

clear trade tc1

set stock tc1 iii.lse

evaluate performance anID trID tcID perftype

print performance tc1

get prob success tc1

get expected return tc1

The trade creator is a useful tool, indeed is central to the entire application, but it cannot help you find a good trade to make - all construction is done by hand. This is a particular problem for options trading, which is very confusing for most people. The reason why options are important is their flexibility - you can use them as directional bets, either up or down, but also allow you to make money from "neither up nor down, stays within a range" or even "moves either up or down" - thus any kind of market knowledge can be used to make a profit, which offers much greater possibilities for the investor than simply trying to "pick a winner".

The true power of options is only really experienced when you use them in combinations, but again this is adding even more complexity - so what can the user do? StockWave solves this problem by searching for trades to make by exhaustively searching for combination trades from an input set of "seed trades"; and to do this we have another form, called imaginatively enough, the Automated Trade Searcher.

Trade Search

ts1 = open trade search tc1 

show option chain iii.lse 

show option price abf.lse yahoo

list available strikes abf.lse lo hi 

set seed trades ts1 tr1 tr2 tr3 [tr4 tr5 tr6] 

run trade search ts1 leveldepth 

sort trades ts1 prob success exp return

sort trades ts1 prob.success

expected return 

max profit

max loss

tr11 = get trade ts1 1 

show trade tr11 tc1

tr11 = get trades ts1 pos1 pos2

show trade tr11 tc1

download option prices

set options trade search

That news affects share prices is a blindingly obvious fact, but curiously most academics, quants and manufacturers of trading software do not wish to accept this, or try to incorporate it into their models; this is because analyzing the news means dealing with text as an input stream and of at least partially understanding language - since this is very difficult, no one wants to even attempt it, hence the fascination with timeseries only models and with, often useless and irrelevant, technical indicators.

StockWave has a suite of news analysis tools that is unique.

News Analysis

ch2 = open news chart abf.lse 

show news ch1

create event stream abf.lse 

show events ch1

build newsarchive iii.lse

na1 = open news analysis iii.lse

create event stream iii.lse

list events before 29 aug 2007 1030 20

list events after 29 aug 2007 1030 4 hours

set events before na1 29 aug 2007 1030 20 minutes

set events after na1 29 aug 2007 1030 4 hours

create trendbreaker iii.lse

show whatif ch1 ceo resigns

price response abf.lse ceo resigns

process news

generate news stats

concept list

build news event model

show news model

Background Research

wa1 = create webagent iii.lse directors dealings

tl1 = get timeline wa1

show timeline ch1 tl1

tch1 = open timeline chart iii.lse tl1

show iii.lse financials

search news 3i directors remuneration

autoupdate db

autoquery

show

search news

create dns

create superfusion

Trade Execution

open trade tr1

create trade alarm tr1 [alarmlevel =  hit stop loss / profit target | green / red | never action = noaction | email]

close trade tr1 

price improvement trID brokerID

Alarms

news alarms on email open

price alarms on email all

create price monitor dow email all 

create news monitor regex abf.lse 

create news monitor mfi abf.lse 

Companies Database

build newsarchive abf.lse

build db webagent

build db yahoo

create db

rs = query db select x from y where z

rs = stock scan criterion

build db webagent

build db yahoo

create db

rs = query db select x from y where z

rs = stock scan criterion

datamine

datamine

sort stocklist

Data Utilities

refresh ts abf.lse

filter ts abf.lse

process prices abf.lse

process news abf.lse 

process news ftse100

upload prices s.m | g

upload news s.m | g

download prices iii.lse

download news iii.lse

download yahoo iii.lse

download historical

General

list forms

list objects

hide portfolio

show ch1

hide ch1

close ch1

destroy objectID

list

print

run script daily

minimize

restore

shutdown

Help

search help myquery

search news myquery

help

help something

help api

show abf.lse financials

Python Module

The python module merely duplicates what is above, except in python - the point of this is that python is a fully featured programming language, with many useful libraries, which can be used to build any type of custom trading system you desire; it is better than c#, visual basic, etc and is totally free.

All python commands "live" in the stockwave module. To use any command you need to import stockwave, create an instance of the application, then call whatever functions you need. The functions are easily understood from looking at the module source code.


class StockWaveApplication(object) :
    """
    StockWave API in Python
    - an instance of StockWave must already be running when you use this
    """
    def __init__(self):
        # you need to set these yourself
        self.executable_ = "C:/StockWave/StockWave.exe"
        self.install_dir_ = "C:/StockWave/"
        self.temp_dir_ = "C:/StockWave/temp/"
    def is_running(self):
        # find the running program
        hwnd = win32gui.FindWindow( "TMain", "StockWave")
        # check hwnd non-null
        if hwnd == 0:
            return False
        else:
            return True
    def run(self):
        #import os
        #os.system('cmd /c ' + self.executable_) # works but leaves a shell window open
        #p = Popen(self.executable_, shell=False)
        #return_code = call("echo Hello World", shell=True)
        # - this might not run because of security restrictions
        si = win32process.STARTUPINFO()
        details = win32process.CreateProcess( self.executable_, self.executable_, None, None, False, 0, None, None, si)
        #win32process.TerminateProcess(details[0],99)
        return #details
    def sendmessage_stockwave( self, cmdmsg ):
        # find the running program
        hwnd = win32gui.FindWindow( "TMain", "StockWave")
        if hwnd == 0:
            return False
        # pack the data we want to send
        CopyDataStruct = "IIP"
        char_buffer = array.array('c', cmdmsg)
        char_buffer_address = char_buffer.buffer_info()[0]
        char_buffer_size = char_buffer.buffer_info()[1]
        cds = struct.pack( CopyDataStruct, 0, char_buffer_size, char_buffer_address )
        # then send it
        win32api.SendMessage( hwnd, win32con.WM_COPYDATA, 0, cds )
        return True
        # the above will fail if the target needs admin privileges to run
#   def postmessage_stockwave( self, cmdmsg ):
#       hwnd = win32gui.FindWindow( "TMain", "StockWave")
#       CopyDataStruct = "IIP"
#       char_buffer = array.array('c', cmdmsg)
#       char_buffer_address = char_buffer.buffer_info()[0]
#       char_buffer_size = char_buffer.buffer_info()[1]
#       cds = struct.pack(CopyDataStruct, 0, char_buffer_size, char_buffer_address)
#       win32api.PostMessage( hwnd, win32con.WM_COPYDATA, 0, cds ) # no, not with postmessage, data would be deleted
#       return
    def execute_command( self, cmd ):
        self.sendmessage_stockwave(cmd)
        return
    def last_error(self):
        filename = self.install_dir_ + "last.error"
        #filename = self.install_dir_ + "scripting/error/last.error"
        f = open(filename)
        txt = f.read()
        f.close()               
        return txt
    def last_output(self):
        filename = self.install_dir_ + "last.output"
        #filename = self.install_dir_ + "scripting/output/last.output"
        f = open(filename)
        txt = f.read()
        f.close()
        return txt
    def last_output_as_list(self):
        filename = self.install_dir_ + "last.output"
        #filename = self.install_dir_ + "scripting/error/last.output"
        f = open(filename)
        lst = f.readlines()
        f.close()
        return lst
    #
    # General Info
    #
    def auto_arrange( self ):
        self.execute_command("autoarrange")
        return self.last_output()
    def get_markets(self):
        self.execute_command( "get markets" )
        return self.last_output_as_list()
    def get_instruments(self, grp):
        self.execute_command( "get instruments " + grp )
        return self.last_output_as_list()
    def get_license(self):
        self.execute_command( "get license")
        return self.last_output()
    def get_version(self):
        self.execute_command( "get version" )
        return self.last_output()
    def get_user(self):
        self.execute_command( "get user" )
        return self.last_output()
    def get_stocks( self, grp ):
        self.execute_command( "get stocks " + grp )
        return self.last_output_as_list()
    def get_locale( self ):
        self.execute_command( "get locale" )
        return self.last_output()
    def set_locale( self, loc ):
        self.execute_command( "set locale " + loc )
        return self.last_output()
    def get_region( self, reg ):
        self.execute_command( "get region " + reg )
        return self.last_output()
    #
    # Data Capture
    #
    def start_datacapture(self):
        self.execute_command( "start datacapture" )
        return
    def stop_datacapture(self):
        self.execute_command( "stop datacapture" )
        return  
    def clear_datasource(self):
        self.execute_command( "clear datasource" )
        return
    def clear_datasource( self, i ):
        self.execute_command( "clear datasource " + i )
        return  
    def load_datasource( self, filename ):            
        self.execute_command( "load datasource " + filename )
        return
    def start_pricecapture(self):
        self.execute_command( "start pricecapture " )
        return
    def start_newscapture(self):
        self.execute_command( "start newscapture " )
        return
    def stop_pricecapture(self):
        self.execute_command( "stop pricecapture " )
        return
    def stop_newscapture(self):
        self.execute_command( "start newscapture " )
        return
    def clear_datasource(self, i):
        self.execute_command( "clear datasource" )
        return
    def create_price_source(self, url, arg, preprocess, frequency, grp):
        self.execute_command( "create pricesource " + url + " " + arg + " " + preprocess + " " + frequency + " " + grp)
        return
    def create_news_source( self, url, frequency, grp ):
        self.execute_command( "create newssource " + " " + frequency + " " + grp)
        return
    def list_price_sources(self):
        self.execute_command( "list pricesource")
        return self.last_output_as_list()
    def list_news_sources(self):
        self.execute_command( "list newssource")
        return self.last_output_as_list()
    #
    # Portfolio
    #
    def create_portfolio( self, pname,  email ): 
        self.execute_command( "create portfolio " + pname + " " + email )
        return
    def show_portfolio(self):
        self.execute_command( "show portfolio" )
        return
    def select_portfolio( self, pname ):
        self.execute_command( "select portfolio " + pname )
        return
    def delete_portfolio(self, pname):
        self.execute_command( "delete portfolio " + pname )
        return self.last_output()
    def show_closed_trades( self, pfl ):
        self.execute_command( "show closed trades " + pname )
        return self.last_output_as_list()
    def show_open_position( self, pfl ):
        self.execute_command( "show open positions " + pname )
        return self.last_output_as_list()
    def list_all_portfolio(self, pfl):
        self.execute_command( "list portfolio ")
        return self.last_output_as_list()
    def get_trades(self, pname): # shows and also returns a list
        self.execute_command( "get trades " + pname )
        return self.last_output_as_list()
    def get_trade_detail( self, pname, tradeID ):
        self.execute_command( "get trade detail " + pname + " " + tradeID )
        return self.last_output()
    def current_position( self, pname ):
        self.execute_command( "current position " + pname )
        return self.last_output()
    def profit_closed_trades( self, pnam ):
        self.execute_command( "profit closed trades " + pname )
        return self.last_output()
    def set_default_broker( self, pfl, bname): 
        self.execute_command( "set default broker " + pname + " " + bname )
        return
    def get_brokers(self, pname):
        self.execute_command( "get brokers " + pname )
        return self.last_output_as_list()
    def get_default_account(self, pname):
        self.execute_command( "get default account " + pname )
        return self.last_output()
    def can_trade(self, pname, stockID ):
        self.execute_command( "can trade " + pname + " " + stockID )
        return self.last_output() 
    def has_CFD(self, pname, stockID):
        self.execute_command( "has CFD " + pname + " " + stockID )
        return self.last_output()
    def has_spreadbet(self, pname, stockID):
        self.execute_command( "has spreadbet " + pname + " "  + stockID )
        return self.last_output()
    def has_options(self, pname, stockID):
        self.execute_command( "has options " + pname + " " + stockID )
        return self.last_output()
    def get_account_balance(self, pname, brokerID):
        self.execute_command( "get account balance " + pname + " " + brokerID)
        return self.last_output()
    #
    # Charting
    #
    def open_chart( self, retobjname, mystock ): 
        cmdstring = retobjname + " = open chart " + mystock
        self.execute_command(cmdstring)
        return retobjname
    def move_chart( self, chartID, l, t, w, h ):
        cmdstring =  "move chart " + chartID + " " + l + " " + t + " " + w + " " + h
        self.execute_command(cmdstring)
        return 
    def zoom_chart( self, chartID, datetime1, datetime2 ):
        cmdstring = "zoom chart " + chartID + " " + datetime1 + " " + datetime2
        self.execute_command(cmdstring)
        return
    #
    # TA
    #
    def open_ta_chart( self, retobjname, mystock ): 
        cmdstring = retobjname + " = open chart " + mystock
        self.execute_command(cmdstring)
        return retobjname
    def move_ta_chart( self, chartID , l, t, w, h ):
        cmdstring =  "move chart " + chartID + " " + l + " " + t + " " + w + " " + h
        self.execute_command(cmdstring)
        return 
    def zoom_ta_chart( self, chartID, datetime1, datetime2 ):
        cmdstring = "zoom chart " + chartID + " " + datetime1 + " " + datetime2
        self.execute_command(cmdstring)
        return
    def show_indicator( self, tachartID, indID ):                 
        cmdstring = "show indicator " + tachartID + " " + indID
        self.execute_command(cmdstring)
        return
    def hide_indicator( self, tachartID, indID ): # ma20 ema boll psar macd w%r rsi                
        cmdstring = "hide indicator " + tachartID + " " + indID
        self.execute_command(cmdstring)
        return
    def create_indicator( self, retobjname, stockID, indID ):                 
        cmdstring = retobjname + " = create indicator " + stockID + " " + indID
        self.execute_command(cmdstring)
        return retobjname # or self.last_output_as_list()
    #
    # Data Selection and Filtering
    #
    def select_data( self, retobjname, datetime1, datetime2, resolution ):
        cmdstring = retobjname + " = select data " + datetime1 + " " + datetime2 + " " + resolution
        self.execute_command(cmdstring)
        return retobjname
    def show_histogram( self, dsID, N ): # N is num bins
        self.execute_command( "show histogram " + dsID + " " + N )
        return
    def get_volatility( self, dsID ):
        self.execute_command( "get volatility " + dsID )
        return self.last_output()
    def show_filter_window( self, fwinID, dselID): 
        cmdstring = fwinID + " = show filter window " + dselID
        self.execute_command(cmdstring)
        return fwinID
    def set_threshold_level( self, fwinID, filtname, thresh ):
        cmdstring = "set threshold level " + fwinID + " " + filtname + " " + thresh
        self.execute_command(cmdstring)
        return
    def get_filtered_data( self, fwinID ):
        cmdstring = retobjname + " = get filtered data " + fwinID
        self.execute_command(cmdstring)
        return retobjname
    def select_data_with_filter( self, dsID, filtname, thresh ):
        cmdstring = retobjname + " = set threshold level " + dsID + " " + filtname + " " + thresh
        self.execute_command(cmdstring)
        return retobjname
    #
    # Probabilistic Analyzers
    #
    def create_analyzer( self, analID, dselID, algparam ):
        cmd = analID + " = " + "create analyzer " + dselID + " " + algparam
        self.execute_command(cmd)
        return analID
    #
    # Complex Trades
    #
    def create_trade( self, tradeID, tradetype, stockID, bid, offer, N, params ):
        cmdstring = tradeID + " = create trade " + tradetype + " " + stockID + " " + bid + " " + offer + " " + N + " " + params
        self.execute_command(cmdstring)
        return tradeID
    def create_composite_trade( self, tradeID, tid1, tid2 ):
        cmdstring = tradeID + " = create compostie trade " + tid1 + " " + tid2 #tradetype + " " + stockID + " " + bid + " " + offer + " " + N + " " + params
        self.execute_command(cmdstring)
        return tradeID
    #3
    #4
    #5
    #6
    def open_trade_creator( self, retobjname, analID ):
        cmdstring = retobjname + " = open trade creator " + analID;
        self.execute_command(cmdstring)
        return retobjname
    def set_analyzer( self, tcID, analID ):
        cmdstring = "set analyzer " + tcID + " " + analID
        self.execute_command(cmdstring)
        return
    def add_trade( self, tcID, tradeID ):
        cmdstring = "add trade " + tcID + " " + tradeID
        self.execute_command(cmdstring)
        return
    def evaluate_performance( self, analID ):
        cmdstring = "evaluate performance " + analID
        self.execute_command(cmdstring)
        return last_output()
    def print_performance( self, tcID ):
        print self.evaluate_performance( tcID )
        return
    def clear_all_trades( self, tcID ):
        cmdstring = "clear all trades " + tcID
        self.execute_command(cmdstring)
        return
    def evaluate_performance( self, analID, tradeID, tcID, perftype ):
        cmd = "evaluate performance " + analID + " " + tradeID + " " + tcID + " " + perftype
        self.execute_command(cmd)
        return self.last_output()
    def get_prob_success( self, tcID ):
        cmd = "get prob success " + tcID
        self.execute_command(cmd)
        return self.last_output()
    def get_expected_return( self, tcID ):
        cmd = "get expected return " + tcID
        self.execute_command(cmd)
        return self.last_output()
    #
    # Automatic Trade Selection
    #
    def open_trade_searcher( self, retobjname, tcID ):
        cmd = retobjname + " = open trade searcher " + tcID
        self.execute_command(cmd)
        return retobjname    
    def set_seed_trades( self, tsID, tradeIDlist ):
        cmd = "set seed trades " + tsID + " " + tradeIDlist
        self.execute_command(cmd)
        return
    def trade_search( self, tsID, level ):
        cmd = "trade search " + tsID + " " + level
        self.execute_command(cmd)
        return
    def sort_tradelist( self, tradelist, criterion ):
        cmd = "sort trade list " + tradelist + " " + criterion
        self.execute_command(cmd)
        return
    def get_trade( self, retobjname, tradelist, pos ):
        cmd = "get trade " + retobjname + " " + tradelist + " " + pos
        self.execute_command(cmd)
        return self.last_output()
    def get_trades( self, retobjname, tradelist, pos1, pos2 ):
        cmd = "get trades " + retobjname + " " + pos1 + " " + pos2
        self.execute_command(cmd)
        return self.last_output_as_list()
    #
    # News Analysis
    #
    def open_news_chart( self, stockID ):
        cmd = "open news chart " + stockID
        self.execute_command(cmd) 
        return
    def process_news( self, stockID ):
        cmd = "process news " + stockID
        self.execute_command(cmd) 
        return
    def create_event_stream( self, stockID ):
        cmd = "create event stream  " + stockID
        self.execute_command(cmd) 
        return
    def create_trendbreaker( self, stockID ):
        cmd = "create trendbreaker " + stockID
        self.execute_command(cmd) 
        return
    def show_whatif( self, chartID, stockID, cevent ):
        cmd = "show whatif " + chartID + " " + stockID + " " + event
        self.execute_command(cmd) 
        return
    def generate_news_statistics( self, stockID ): 
        cmd = "generate news statistics " + stockID
        self.execute_command(cmd) 
        return
    def build_concept_list( self, stockID ):
        cmd = "build concept list " + stockID
        self.execute_command(cmd) 
        return
    def generate_news_event_model( self, retobjID, mystockID ):
        cmd = retobjID + " = generate news event model " + stockID
        self.execute_command(cmd) 
        return retobjID
    def show_news_model( self, retobjID, nemID ):
        cmd = "show news event model " + stockID
        self.execute_command(cmd) 
        return retobjID      
    def list_possible_events( self, retobjname, nemID, mystockID ):
        cmd = "list possible events " + nemID + " " + stockID
        self.execute_command(cmd)       
        return last_output_as_list()
    def show_news( self, chartID ):                
        cmd = "show news " + chartID
        self.execute_command(cmd) 
        return
    def process_news( self, stockID ):
        cmd = "process news " + stockID
        self.execute_command(cmd) 
        return
    #upload prices s.m | g
    #upload news s.m | g
    def build_newsarchive( self, stockID ):                
        cmd = "build newsarchive " + stockID
        self.execute_command(cmd) 
        return
    #
    # Data Fusion
    #
    def create_dynamic_noise_source( self, retobjID, nemID ):
        cmd = retobjID + " = create dynamic noise source " + nemID
        self.execute_command(cmd)     
        return retobjID
    def create_fusion_analyzer( self, retobjname, dns, ds1, params ):
        cmd = retobjname + " = create fusion analyzer " + dns + " " + ds1 + " " + params
        self.execute_command(cmd)  
        return retobjname
    def show( self, formID ):
        cmd = "show " + formID
        self.execute_command(cmd)      
        return
    #
    # Deep Web Search
    #
    def create_webagent( self, retobjname, stockID, criteria ):
        cmd = retobjname + " = create web agent " + stockID + " " + criteria
        self.execute_command(cmd)
        return retobjname
    def update_db_from_raw( self, stockID, criteria, rawdata ):
        cmd = "update db from raw " + stockID + " " + criteria + " " + rawdata
        self.execute_command(cmd)
        return
    def autoquery(self, stockID, question ):
        cmd = "autoquery " + stockID + " " + question
        self.execute_command(cmd) 
        return self.last_output()
    def get_timeline( self, webagentID ):
        cmd = "get timeline " + webagentID
        self.execute_command(cmd)         
        return self.last_output_as_list()
    def show_timeline( self, chartID, tlID ):
        cmd = "show timeline " + chartID + " " + tlID
        self.execute_command(cmd) 
        return
    def show( self, stockID, rightclickSubject ):
        cmd = "show " + stockID + " " + rightclickSubject
        self.execute_command(cmd) 
        return
    def search_news( self, stockID, whatyouwant ):
        cmd = "search news " + stockID + " " + whatyouwant
        self.execute_command(cmd) 
        return self.last_output_as_list()
    #
    # Trade Execution
    #
    def open_trade( self, chosentradeID, pflname, brokerinfo ):
        cmd = "open trade " + tradeID + " " + pflname + " " + brokerinfo
        self.execute_command(cmd)
        return
    def close_trade( self, chosentradeID ): 
        cmd = "close trade " + tradeID
        self.execute_command(cmd)
        return
    #stw.price_improvement( chosentrade, brokeraccount )
    #stw.price_improvement( chosentrade, "newbid1 newoffer1" )
    #
    # Alarms
    #
    def set_trade_alarm( self, chosentradeID, stoploss, profittarget, warnlevel ):
        cmd = "set trade alarm " + tradeID + " " + stoploss + " " + profittarget + " " + warnlevel
        self.execute_command(cmd)
        return
    def set_price_monitor( self, chosentradeID, maxneg, maxpos, timeperiod ): 
        cmd = "set price monitor " + tradeID + " " + maxneg + " " + maxpos + " " + timeperiod
        self.execute_command(cmd)
        return
    def set_price_spikes( self, stockID, action ):
        cmd = "set price spikes " + stockID + " " + action
        self.execute_command(cmd)
        return
    def set_news_monitor_mfi( self, tradeID, minmag, fmin, fmax, mininteg ): 
        cmd = "set news monitor mfi " + tradeID + " " + minmag + " " + fmin + " " + fmax + " " + mininteg
        self.execute_command(cmd)
        return
    def set_news_monitor_regex( self, tradeID, regex ):
        cmd = "set news monitor regex " + tradeID + " " + regex
        self.execute_command(cmd)
        return
    def set_news_monitor( self, eventslist ):
        cmd = "set news monitor " + eventslist
        self.execute_command(cmd)
        return
    def set_news_alarms( self, stockID, action ):
        cmd = "set news alarms " + stockID + " " + action
        self.execute_command(cmd)
        return
    #
    # Datamining Fundamentals
    #
    def datamine( self, retobjname, conditions ):
        cmd = retobjname + " = datamine " + conditions
        self.execute_command(cmd)    
        return retobjname
    #
    # Database 
    #
    def build_db( self, dbname, csv, tableheadings ):
        cmd = dbname + " = build db " + csv + " " + tableheadings
        self.execute_command(cmd)
        return dbname
    def query_db( self, retobjname, sqlstring ):
        cmd = "query db " + sqlstring
        self.execute_command(cmd)
        return self.last_output_as_list()
    def basic_scan( self, retobjname, conditions ):
        cmd = retobjname + " = basic scan " + conditions
        self.execute_command(cmd)     
        return self.retobjname
    def sort_stocklist( self, stockID, condition ):
        cmd = "sort stocklist " + stockID + " " + condition
        self.execute_command(cmd)
        return
    def run_scanner(self, condition):
        self.execute_command( "run scanner " + condition )
        return self.last_output_as_list()
    def datamine_companies(self, criterion):
        self.execute_command( "datmine " + criterion )
        return self.last_output_as_list()
    #
    # Quote Downloads
    #
    def download_prices( self, stockID ):
        cmd = "download prices " + stockID
        self.execute_command(cmd)
        return
    def download_yahoo( self, stockID ):
        cmd = "download yahoo " + stockID
        self.execute_command(cmd)  
        return
    def get_available_strikes( self, strikeslist, mystock, expdate, origin, maxnumstrike ):
        cmd = "get available strikes " + strikeslist + " " + mystock + " " + expdate + " " + origin + " " + maxnumstrikes
        self.execute_command(cmd) 
        return self.last_output_as_list()
    def download_option_prices( self, mystock, origin ):
        cmd = "download option prices " + stockID + " " + origin
        self.execute_command(cmd)
        return
    def options_trade_search( self, ots, ds, an, strikes, level ):
        cmd = "options trade search " + ots + " " + ds + " " + an + " " + strikes + " " + level
        self.execute_command(cmd)  
        return
    def show_options_chart( self, chartID ):            
        cmd = "show options chart " + stockID
        self.execute_command(cmd) 
        return
    def download_historical(self, mystock):                
        self.execute_command( "download historical prices " + mystock )
        return self.last_output_as_list()
    def download_prices(self, mystock):                
        self.execute_command( "download prices " + mystock )
        return self.last_output_as_list()
    def download_news(self, mystock):                
        self.execute_command( "download news " + mystock )
        return self.last_output_as_list()
    #
    # Data Utilities
    #
    def refresh_ts(self, stockID):
        cmd = "refresh ts " + stockID
        self.execute_command(cmd) 
        return
    def filter_ts(self, stockID):
        cmd = "filter ts " + stockID
        self.execute_command(cmd) 
        return
    def process_prices(self, stockID):            
        cmd = "process prices " + stockID
        self.execute_command(cmd) 
        return
    #convert_metastock
    #import_yahoo_csv
    #import_csv
    #
    # General
    #
    def shutdown(self):
        cmd = "shutdown"
        self.execute_command(cmd) 
        return
    def exit(self):
        cmd = "exit"
        self.execute_command(cmd) 
        return
    def list_all_forms(self):
        cmd = "list all forms"
        self.execute_command(cmd) 
        return self.output_as_list()
    def list_all_objects(self):
        cmd = "list all objects"
        self.execute_command(cmd) 
        return self.last_output_as_list()
    def run_script( self, sname ):
        self.execute_command( "run script " + sname)
        return self.last_output()
    def backtest_rule(self, trading_signals):
        cmd = "backtest rule " + trading_signals
        self.execute_command(cmd) 
        return self.last_output_as_list()
    def plot(self, tseries ):
        cmd = "plot " + tseries
        self.execute_command(cmd) 
        return
    #
    # send pictures and analysis to user email
    #
    def print_analysis(self, tcID ):
        cmd = "print analysis " + tcID
        self.execute_command(cmd) 
        return
    def print_chart(self, chartID ):
        cmd = "print chart " + chartID
        self.execute_command(cmd) 
        return
    def email(self, pflID, msg, attach ):
        cmd = "email " + pflID + " " + msg + " " + attach
        self.execute_command(cmd) 
        return

#
# now put it all together in a simple test
#
def basic_test():
    #import stockwave
    stw = stockwave.create()
    stw.run()

    stw.start_datacapture()
    stw.stop_datacapture()
    stw.clear_datasource()
    stw.load_datasource()

    stw.create_portfolio("test user 00", "noone@nomail.com")
    stw.show_portfolio()         
    stw.select_portfolio("test user 00")

    mystock = "abf.lse"
    stw.download_historical(mystock)
    stw.download_prices(mystock)
    stw.download_news(mystock)

    ch1 = stw.open_chart("ch1", mystock)
    stw.move_chart( ch1, 20, 30, 200, 300)
    stw.zoom_chart( ch1, "13 aug 2006 0900", "10 apr 2007 1130")

    ds1 = stw.select_data( "ds1", mystock, "13 aug 2006 0900", "10 apr 2007 1130", "15 minute")

    fw1 = stw.show_filter_window( "fw1", ds1, "dau8" )
    stw.set_threshold_level( fw1, 0.04 )
    ds2 = stw.select_data_with_filter( "ds2", ds1, "dau8", 0.04 );

    an1 = stw.create_analyzer( "an1", ds1, "10000 rw 50")
    while stw.is_task_completed(an1) == False:
        os.sleep(1000)
    #an2 = stw.create_analyzer( "an2", ds1, "10000 bcor ")
    #an3 = stw.create_analyzer( "an3", ds1, "10000 bpn ")
    #an4 = stw.create_analyzer( "an4", ds1, "10000 rnn ")
    #an5 = stw.create_analyzer( "an5", ds2, "10000 som")

    anal = [an1 ] #,an2,an3,an4,an5]

    tc1 = stw.open_trade_creator("tc1", an1)
    stw.add_trade( tc1, "call 510 oct bid offer numcontracts" )
    stw.evaluate_perf(tc1)
    stw.print_perf(tc1)
    stw.email_perf(tc1, "noone")
    stw.clear_all_trades(tc1)
    stw.hide(tc1)

    # can also just make trades on their own without using a trade creator
    # tradeID = create_trade( "tradetype action self, symbol.market bidprice offerprice numbercontracts ) 
    t1 = stw.create_trade( "t1", mystock, "share buy bid offer 1000")
    t2 = stw.create_trade( "t2", mystock, "cfd sell bid offer 1500")
    t3 = stw.create_trade( "t3", mystock, "call strike buy bid offer 5")
    t4 = stw.create_trade( "t4", mystock, "put stike  sell bid offer 10")
    t5 = stw.create_trade( "t5", mystock, "spreadbet sell bid offer 2500")

    # make a composite trade, here buying a call and selling a put - this is a
    t6 = stw.create_composite_trade(t3, t4)
    trades = [t1,t2,t3,t4,t5,t6]

    # inspect these as well if you want
    tc2 = stw.open_trade_creator("tc2")
    stw.set_analyzer(tc2, an1);
    stw.show_trade( t1, tc2 )
    stw.show_trade( t2, tc1 )
    stw.close(tc2)

    # making a trade
    t1 = stw.get_trade(tc1)
    stw.execute_trade( t1, "gaza mybroker")
    t1 = stw.get_trade(tc1)
    stw.open_trade(t1, "gaza", "mybroker")
    stw.set_trade_alarm( t1, stoploss, profittarget, "warnlevel" )
    stw.set_price_monitor( t1, "-5. 5. 15.0")
    stw.set_news_monitor_mfi( t1, 4.5, -.5, .5, 0.)
    stw.set_news_monitor_regex( t1, "FDA | approval | settlement")

    # or use trade search instead, its much easier
    tt = stw.open_autosearch("tt", tc1, tr1, tr2, tr3, tr4, tr5 )

    #alltrade = []
    for i in range(6):
        stw.trade_search(tt,i) # appends to the end

    # see what we've got
    alltrade = stw.get_trades(tt)
    stw.sort(alltrade, "prob success")
    highprob = stw.get_trades(alltrade,0,5)
    stw.sort(alltrade, "expected return")
    highreturn = stw.get_trades(alltrade,0,5)
    possibletrades = highprob + highreturn
    stw.print_trade_list(tt)
    possibles = intersect(highp, highe)
    tbest3 = stw.get_found_trade(tt,3);
    tbest1 = stw.get_best_trade(tt,"expected return");
    tbest2 = stw.get_best_trade(tt,"prob success");
    possibles = [tbest1, tbest2, tbest3]

    if( len( possibletrades ) > 0 ):

        # take the best
        chosentrade = possibletrades[0]

        # execute the trade on the chosen broker account
        stw.open_trade( chosentrade, "gaza", brokerinfo )

        # trade alarms vary from "never warn" -> stoic -> normal -> jumpy -> paranoid
        stw.set_trade_alarm( chosentrade, stoploss,  profittarget, "paranoid" )

        # we can set stoplosses and profit targets
        # stw.set_autoclose_on( chosentrade, -1000., 2500., onclose = "inquest on failure")
        # we can set news alerts as well
        stw.set_news_alarms( mystock, "email pfl" )
        stw.set_price_spikes( mystock, "email pfl" )

        # do news event analysis
        stw.process_news(mystock)
        stw.create_event_stream(mystock)
        stw.create_trendbreaker(mystock)
        stw.show_whatif( ch1, mystock, "ceo resigns")

        # news event model
        stw.generate_news_stats()

        # stress-test what if
        # send these back to user {possible event, timescale, likely move}
        # superfusion
        nevis = stw.generate_news_event_model("nevis",mystock)
        mb = stw.show_news_model("mb", nevis)
        lpe = stw.list_possible_events(nevis,mystock)

        for e in lpe:
            ch1 = stw.show_whatif(mystock,e)
            time.sleep(5000)
            stw.close(ch1)
        dns = stw.create_dynamic_noise_source(nevis)
        fan1 = stw.create_fusion_analyzer( dns, ds1, "rw 10000 50 yes")	

    else :
        print "no trades found"
#end of basic test