Investment Studio > Getting started > Full speed ahead!
In the previous section, we created a portfolio, added some assets to it and spruced it up with objects from the Gallery. But what about the Grid objects in our portfolio?
>>> What about them? <<<
To start with, can you tell me where they are?
>>> Come on, give me some credit! There is a portfolio-specific Grid in the Assets view, one in the Quotes view and one in the Transactions view. <<<
Excellent. And what does "portfolio-specific" mean?
>>> Sigh. It means that those Grids display properties of the selected portfolio exclusively, including its assets and transactions. <<<
Yes, but it also means that the setup of those Grids is specific to the selected portfolio. The Grid in the Assets view of portfolio "A" need not look anything like the Grid in the Assets view of portfolio "B", even if the two portfolios are otherwise identical. And I'm not just talking about superficial features like the Grid's size, position and orientation. I'm talking about the Grid's record definition.
>>> Now you lost me. What's a "record definition"? <<<
Consider the Grid in the Assets view. For definiteness, let's say it's set up for rowwise orientation: each row describes an asset in the portfolio. Each row can then be viewed as a record in a database, each cell in the row as a field in that record. The record definition tells the Grid object what goes into each field (e.g. the asset's name in the first field, the asset's symbol in the second field, the asset's NAV in the third field and so on) and how each field should be formatted. All records in the Grid have the same structure, determined by the Grid's record definition.
>>> And each portfolio-specific Grid has its own, customizable record definition? <<<
Yes, and so does the Grid in the Portfolios view.
Let's get practical. With our new portfolio still selected, switch to the Quotes view.
>>> Clicking the Quotes tab... we're there. I see a handsome stranger in this Grid's future... <<<
Why, tank you. To open the
Grid's record definition editor, click the Setup
button
in
the Grid's toolbar or Customize > Setup in the Grid's pop-up
menu.
>>> Done. Hm, this looks almost like a spreadsheet! <<<
That's not a bad comparison. Many (usually most) record fields get their values from expressions written in a spreadsheet-like syntax. The main difference is that record fields are not automatically named like cells in a spreadsheet. Instead, it's your responsibility to assign (hopefully) mnemonic symbols to them when the need arises. So, instead of defining a field's value as "A9 - A15", you might find yourself writing something like "_CLOSE - _PREVIOUS_CLOSE".
At this point, I suggest that you read up on the record definition editor before you continue.
>>> Please go on. <<<
OK. Delete all records in the Quotes view's Grid.
>>> What?!? <<<
Just delete them. We're going to build a simple record definition from scratch, so first of all we need to get rid of the old stuff. In the record definition editor, select the top record field and keep pressing Ctrl-Del (or clicking the Delete button in the editor's toolbar) until all record fields are gone. Then click Apply to see the effect on the Grid without closing the editor.
>>> Surprise: the Grid is now empty. <<<
Right. Empty record definition
yields empty records. Now let's add a single record field. Still
in the record definition editor, press Ins or click the New
button
in the toolbar.
>>> OK, now I have an empty row. <<<
Select it...
>>> How? <<<
Click anywhere in the row. Now look at the Field type combo box in the editor's toolbar. It should show that the field's data type is String, since that's the default type. Use the spin button in the combo box to change the data type to Integer. Next, enter the word "Test" under Header and the value 1 under Definition. Click Apply again. What do you see in the Grid?
>>> A header saying "Test" and a bunch of data cells containing the number 1. <<<
Right. The Grid in the Quotes view contains a record for each variable price asset, and our simple-minded record definition specifies the content of all those records to be identical: a single integer cell with value 1. This is useless, of course, so let's improve it a bit. In the record definition editor, select our lone record field, then use the combo box in the toolbar to change its type to Asset name. Click Apply again. Now what do you see in the Grid?
>>> Each data cell now displays the name of a variable price asset in the selected portfolio. <<<
Indeed. Record fields of type Asset name yield Grid cells which expose the name of their record's asset.
>>> Why do you say "expose"? Don't you just mean "display"? <<<
Right now I might, since all
cells in the Grid are read only (all new fields are created that
way). But if you were to select their record field, unmark the Read
only button
in the editor's toolbar and click Apply,
the Grid would allow all asset names to be edited. Which is why I
say "expose" rather than "display".
By the way, I'm only speaking hypothetically here. Allowing asset names to be edited in the Quotes view is NOT a good idea, since constant price assets are not included in its Grid. Asset names should be editable in Assets view only.
>>> Tell, me what became of the 1 in the record field's Definition column? <<<
It's ignored because of the field's data type.
>>> So the Grid sets the value of each Asset name cell not to 1, but rather to the name of the respective record's asset? <<<
Don't you wish things were that simple? But no... Asset name is a lookup data type. Therefore, what you see in the Grid is not the values of these cells, but rather the values referenced by them.
>>> Say again? <<<
An Asset name cell is a pointer. Its value is an index into a data table. The Grid displays the table entry referenced by the cell. All lookup data types work this way.
>>> Ugh... do I really need to know this? <<<
Yes... kind of. The important point is that the cell's value is an asset index. It uniquely identifies the record's asset and can be used as an argument with all asset lookup functions.
>>> Example, please! <<<
All right. Let's define a new record cell which displays the asset's closing price at the end of the view's date range. To compute the cell's value, we'll use the function ASSET_CLOSE. This function takes two arguments: an asset index and a date. For the date, we'll use the symbol TO_DATE (built into the Grids in the Portfolios, Assets and Quotes views). For the asset index, we'll use a reference to the record's asset name cell.
>>> If we are going to reference it, we must assign a symbol to its record field, right? <<<
Right. In the record field editor, select the field (still the only one) and enter "_asset_name" (without the quotation marks) under Symbol.
>>> What's the leading underscore in the "_asset_name" for? <<<
It's just a convention to distinguish user-defined symbols from built-in identifiers. In fact, "asset_name" without the leading underscore is the name of a built-in function. You want to avoid that kind of name conflict.
By the way, while you're at it, you may also want to change the field's Header from "Test" to the more descriptive "Name".
>>> Done. Now what? <<<
Press Ins to create a new record field. Enter "Close" as its Header and "asset_close(_asset_name, to_date)" as its Definition (again, without the quotation marks).
That's it. Click OK to close the record definition editor and admire the result. (If you see no quotes in the Grid, you may have to adjust the view's date range; ASSET_CLOSE returns an error on dates without a close).
>>> Remarkably, it works. But does this mean that I always need an Asset name field in my Assets and Quotes Grids? <<<
No. It certainly makes sense to display the asset name, but any asset type will do just as well. You can have any number of asset type fields in a record definition. References to such fields all return the same asset index value, so they can be used interchangeably.
Needless to say, asset types do not belong in the Portfolios and Transactions Grids. In the Portfolios Grid, you would use portfolio types and portfolio lookup functions; in the Transactions Grid, you would use transaction types and transaction lookup functions. But the principle remains the same. You will find view-specific details on editing Grid definitions in the sections on Portfolios, Assets, Quotes and Transactions Grid fields.
>>> I note that you haven't said anything yet about formatting Grid cells. <<<
And I won't either. All that is covered by the section on the record definition editor, and is quite easy to try out on your own. If you've followed me this far, you should have no problem with such minor details. You already know the important stuff. Building more complex Grid record definitions is now just a matter of adding more fields, entering expressions for cell values and specifying display formats. Have fun!
>>> Suppose I need a Chart or a Graph that's not available in the Gallery. How do I build it? <<<
Look for the closest match in the Gallery and use it as your starting point. If you're lucky, it may then be sufficient to tweak the new object's display options using its pop-up menu. To see how, please read the Chart and Graph overviews. Note in particular that the Sliders dialog allows data source parameters to be modified on the fly, and that new data sources can be added using the Data > Favorites menu.
>>> Aren't favorites the same as Gallery entries? <<<
No. The Gallery contains complete objects, each one with its own display settings and any number of data sources. A Chart or Graph favorite is an individual data source which can be added to an existing Chart or Graph.
>>> Any Chart or Graph? <<<
In principle, yes. In practice, favorites should be used in context. For instance, suppose you have a Chart which displays the selected portfolio's NAV. You could certainly add a favorite which displays (say) Bollinger bands for the selected asset. But doing so would not make much sense. You need to keep in mind that favorites, like all data sources, include a specification of where the underlying quotes should come from (all assets in the portfolio, the selected asset, the selected portfolio...). They are not just add-ons which plug into a Chart's or a Graph's existing data sources. They are complete data sources in their own right.
>>> But I could add an asset-oriented favorite to a portfolio-oriented Chart and then modify the new data source to work with portfolio NAVs instead of asset closes, right? <<<
Absolutely. But that requires editing the Chart's data sources. Which brings us to the core of the topic at hand.
>>> Isn't it two topics? I mean, Charts and Graphs are different objects. <<<
True, but they really have lots in common. Both plot functions of an independent variable, X. The fundamental difference lies in how the range of this independent variable is computed. Charts simply step X through the view's date range in one-day steps, from the first date to the last date. Graphs are more flexible: they let you specify the start X, the end X and the number of steps in X (in fact, they require that you do so). In a Graph, X need not even be a time variable; it could be the number of a bin in a frequency distirbution, for instance. There are other differences too, of course (support for candlesticks and profiles in Charts, support for point markers in Graphs) but this is the crucial one.
>>> So editing Chart sources and Graph sources is pretty much the same thing? <<<
Pretty much, yes. Once you understand Chart sources, Graph sources should be no problem.
At this point I suggest that you read the overview of the Chart source editor, then compare it with the overview of the Graph source editor.
>>> Pretty similar indeed... How about an example now? <<<
OK, let's create a simple Chart that compares the price performance of all assets in the selected portfolio and highlights the selected asset. We'll use two data sources: one that plots all assets in gray, one (overlayed on the former) that plots the selected asset in black. To make things interesting, we'll start from scratch with a blank Chart object. To create one...
>>> ... I click Gallery
> Clear default in
the pop-up menu of an existing Chart, then I click the New
chart button
in the view's toolbar. Surely you didn't
think I'd forgotten? <<<
Impressive. I suggest that you create the new Chart in the Quotes view of our usual experiment portfolio. After all, we've messed it up so badly already that it can't get much worse... When the blank Chart is in place, click Data > Sources in its pop-up menu to open the source editor.
>>> Done. <<<
Let's add the first source, then.
In the source editor's toolbar, click the New
button
. In
the source table, make sure that the new source is selected, then
use the Source type combo box in the toolbar to
change its type to Assets: all. This causes the source
to loop through all assets in the selected portfolio and output a
separate set of Chart data for each one.
We still haven't told the Chart source what kind of data it should create, though. That's done in the output channels panel, below the source table. In the panel's Close field, enter the expression "asset_close(self, x)". You already known about the function ASSET_CLOSE and the independent variable X. SELF is another built-in symbol. When the data source is asset type, SELF is the asset index for the asset being plotted; when the data source is portfolio type, SELF is the portfolio index for the portfolio being plotted.
At this point, you can click Apply for a first test run. The axes probably won't look anything like you want them, and there will be no captions to be seen, but those are display options which you can take care of later using the Chart's pop-up menu.
>>> OK, but how can I compare asset performance when each asset starts at a different price? Besides, they are all plotted in black. Weren't we supposed to make them gray? <<<
You have a point. Or two. Let's go back to the source table. To make assets directly comparable, check Indexed. This way, all closes will be normalized to 100 on the first quote. Next, change the Color to gray. Then click Apply again.
>>> Much better! Shall we add the source for the selected asset now? <<<
Yes. This one's easier. With the
first source still selected, click Copy
in the toolbar.
This gives us a second source with the same properties as the
first one. Change its type to Asset: selected and its Color
to black. You may also want to incrase the pen Width
to 2.
That's all. Since the new source is positioned below the old one in the source table, it will be drawn last and therefore end up where we want, on top of the other plots.
Click OK to close the source editor and verify that selecting an asset in the view's Grid causes the selected asset to be highlighted in the Chart.
>>> Indeed... but something's still bothering me. What if the assets in my portfolio are quoted in different currencies? When that happens, this Chart compares apples and oranges! <<<
True. In order to fix that we need to convert all asset closes to a common currency. The obvious choice is the portfolio currency. Plotting this expression will do the trick:
currency_convert(asset_currency(self), portfolio_currency(portfolio), x, asset_close(self, x))
>>> One more thing: we still haven't looked at Symbols and Parameters. <<<
Nothing to it. Defining symbols is rather like creating Grid record definitions, only easier; after all, with symbols you don't have to worry about data types (symbols are always floats or arrays) and display options (symbols are never displayed, only referenced in expressions). Parameters are even simpler. Read the sections on Chart symbols and Chart parameters and you're all set (the Graph equivalents work the same way).
>>> The other day I was chatting with a guy who claimed to have a fool-proof system for trading the XAU. <<<
The Philadelphia exchange's index of gold and silver producers?
>>> Yes. He claimed to have only two rules. If the XAU closes above the previous day's high, buy at the next day's close. If the XAU closes below the previous day's low, sell at the next day's close. He said it would actually be better to trade at the open, but that it's impractical to do so, because he uses an index fund designed to track the XAU, and the fund's daily price is set after the close. <<<
This sounds way too good to be true. But the only way to know for sure is to try it.
>>> I was hoping you would say that... are we going to build a trading system? <<<
Yes, a simple one involving only two assets: a cash position and a 1-for-1 XAU tracker. We'll give it 10000 USD in cash and let it buy and sell the XAU tracker according to this guy's rules. Is our usual demo portfolio still selected?
>>> Sure. <<<
Good. Then select the Assets view and delete all assets in the portfolio. Next, add a constant price asset with symbol CASH and a variable price asset with symbol XAU. Make sure that the currency for both is USD.
If you don't already have a XAU download item, you can easily create one following the example in the previous section (the Yahoo symbol is ^XAU; be sure to drop the "^" in the asset symbol so as to avoid confusion with the exponential operator).
>>> Done. <<<
Switch to the Transactions view. You should see two null transactions, one for each asset.
Select the XAU transaction and
use the First quote button
to move the
transaction to the first available quote date. Then change the
number of units, principal value and fees to 0. This will be our
initial XAU position. You may want to say so in the transaction's
comment field, if one is available.
Next, select the CASH transaction. Set it to the same date as the XAU transaction and enter 10000 for units and principal value, 0 for fees. This will be our initial CASH position. Again, you may want to add a comment to that effect if a comment field is available in the Grid.
>>> Done. <<<
Talking about Grid fields, there are two which you should add to the Grid's record definition (if not already included). One is a String-type custom property called "_COMMENT", the other is the "soft transaction" flag. Their role is explained in the section on Transactions Grid fields.
>>> I see. One allows the system to display comments and the other identifies system-generated transactions. Please continue. <<<
It's time for the trading system proper. Switch to the System view.
>>> This looks vaguely familiar... it reminds me of the Chart and Graph source editor. Three tabbed sections, with Symbols and Parameters in sections #2 and #3. <<<
You're right, the principle is the same. The system's output is generated by stepping through the system's date range, evaluating the Rules at each step. As in Charts and Graphs, the heavy work is best performed under Symbols, while sweepable numerical quantities can be defined under Parameters.
Please read the overview of the System view, then return here.
>>> I'm back. Please continue. <<<
Let's start with the Rules. A simple two-asset system like ours will almost always have the same structure: two rules for buying and two rules for selling.
>>> Why two rules for each action? Shouldn't one be sufficient? <<<
Remember, each record in the Transactions view only describes a flow into or out of a single asset. The complete description of what you'd intuitively call a "transaction" - trading an asset for another - therefore requires at least two transaction records. Each rule generates one kind of transaction record, so you need at least two rules to describe the act of trading CASH for XAU (buying XAU) and two rules to describe the act of trading XAU for CASH (selling XAU). The result is something like this:
| Nr | Asset | Condition | Units | Principal | Fees | Message |
| 1 | CASH | _buy | -_buy_cost | -_buy_cost | 0 | "Rule #" & RULE |
| 2 | CASH | _sell | _sell_proceeds | _sell_proceeds | 0 | "Rule #" & RULE |
| 3 | XAU | _buy | _buy_units | _buy_value | _buy_fees | "Rule #" & RULE |
| 4 | XAU | _sell | -_sell_units | -_sell_value | _sell_fees | "Rule #" & RULE |
>>> Hold it! What's all that stuff with leading underscores? User-defined symbols? <<<
Yes. As usual, the leading underscore is just a convention to prevent confusion with built-in identifiers (such as the RULE symbol used in the Message column).
When writing rules, I prefer to keep convoluted expressions to a minimum and use symbols with descriptive names instead. It makes the rules much more readable, and much easier to maintain. The only exception is the non-essential Message column, where I don't mind long expressions.
>>> And all those symbols are defined under Symbols? <<<
Yes. We'll go there shortly. But
first, please acquaint yourself with the Rules
section and use the New
button
in its
toolbar to duplicate the four rules in the table above. Be sure
to read about the Rules grid and understand the meaning of all fields in the
grid.
Also, before we continue, set the system's date range to a reasonable test period (e.g. 1/1/1999 to 12/31/2001) within the available XAU quote range.
>>> Done. <<<
Select the Symbols section, read all about it, then return here.
>>> Please go on. <<<
The first thing we need is XAU quotes. Hence our first symbol definition:
| _xau_dohlc | asset_quotes(XAU, "ohlc", from_date - 5, to_date) |
Note the use of the asset symbol XAU, without any surrounding quotation marks. In the System view, asset symbols written this way are automatically translated to asset indices.
Since _xau_dohlc does not depend on the date variable X, it will only be evaluated once, at the start of system execution. The 5 days subtracted from the system's start date allow us to hit the pavement running: our trading rules require that we look back a couple of days, and we may be starting the system right after a holiday.
In the course of system execution, determination of how we should trade on date X requires knowledge of the XAU's high and low two trading days before X, and of the XAU's close one trading day before X:
| _quote_dates | index(array(_xau_dohlc), 0, 1) |
| _x_row | match(x, array(_quote_dates), 1) |
| _xau_m2_h | index(array(_xau_dohlc), _x_row - 2, 3) |
| _xau_m2_l | index(array(_xau_dohlc), _x_row - 2, 4) |
| _xau_m1_c | index(array(_xau_dohlc), _x_row - 1, 5) |
The auxiliary date vector _quote_dates is good to have for efficiency reasons. Since it doesn't depend on X, it too is computed only once. If we had combined its definition with the definition of _x_row (the only place where _quote_dates is actually used), the result would have been more concise, but also slower.
_x_row is the row number in _quote_dates, and hence in _xau_dohlc, of the closest (preceding or equal) match to the evaluation date X. In the definition of _xau_m2_h, we get the XAU's high two rows (and hence two trading days) before _x_row. _xau_m2_l is the XAU's corresponding low, and _xau_m1_c is the XAU's close on the subsequent trading day.
>>> Isn't this a bit roundabout? Why don't you just look up the quotes by subtracting 1 or 2 days from X? <<<
Because those would be calendar days, not trading days. Consider an ordinary Monday: X - 2 would be Saturday, X - 1 Sunday. If you tried to vlookup the quotes with range matching, both X - 2 and X - 1 would actually return the quote for X - 3 (Friday). Working with row numbers rather than dates solves this problem.
So much for decision-making. When it comes to generating transactions, the opposite problem presents itself. X steps through all calendar days, including untradeable ones like (in this case) Saturdays and Sundays. If we rely on _x_row for the day's price, we'll always get a quote, even on weekends (typically the preceding Friday's). We could put checks in place to exclude such days, but an easier way is to use a separate call to asset_close, which returns an error (#N/A) if there is no quote for the requested date:
| _close | asset_close(XAU, x) |
A rule can't generate a transaction if one or more of its core properties (condition, units, principal, fees) are on error. To ensure that no transactions will be generated on days without a XAU quote, it's therefore enough to make a core property of every rule dependent on _close.
We now have all we need to define the symbols in the Rules section:
| _fees | 1% |
| _sell_units | asset_units(XAU, x) |
| _sell | (_sell_units > 0) and (_xau_m1_c < _xau_m2_l) |
| _sell_value | _sell_units * _close |
| _sell_fees | _sell_value * _fees |
| _sell_proceeds | _sell_value - _sell_fees |
| _buy_units | int(asset_nav(CASH, x) / (_close * (1 + _fees))) |
| _buy | (_buy_units > 0) and (_xau_m1_c > _xau_m2_h) |
| _buy_value | _buy_units * _close |
| _buy_fees | _buy_value * _fees |
| _buy_cost | _buy_value + _buy_fees |
Note that we've assumed a flat fee of 1% for buying and selling XAU shares.
Enter the above symbol definitions and switch to the Portfolios view. The system will be automatically executed when you exit the System view. When it's finished, you should be able to read off the result in the Portfolios Grid.
>>> Wow... from 10000 to 1853.73 USD in two years. That's a loss of 81.46%. <<<
Don't give up quite yet. If you look at the portfolio's NAV chart, you'll see the kind of asymptotic decline typical of overtrading. Switch to the Transactions view and you'll see that the system traded no less than 172 times in those two years. That's a lot, and it suggests that the result might improve if we slow things down a bit.
Try changing the definition of _sell_units to
int(_sell_fraction * asset_units(XAU, x))
and the definition of _buy_units to
int(_buy_fraction * asset_nav(CASH, x) / (_close * (1 + _fees)))
This gives us two "confidence" knobs, _sell_fraction and _buy_fraction, which can be turned between 0 and 1: the closer to 1 we go, the more our system will trade. We could look for the best combination manually, but why not let our computer do the hard work?
>>> Are you talking about automated parameter optimization? <<<
Indeed. Switch to the Parameters section, read up on it here, then enter the following parameter definitions:
| Symbol | Value | Low | High | Steps |
| _buy_fraction | 1 | 0 | 1 | 11 |
| _sell_fraction | 1 | 0 | 1 | 11 |
>>> Done. <<<
With both _buy_fraction and _sell_fraction set to 1, our modified system should work just like before. You can check that you didn't make a mistake somewhere by switching back to the Portfolios view and verifying that the system still yields the same catastrophic result.
>>> Works fine... if that's the word. <<<
Excellent. Go back to the System
view and click the Optimize button
in
the Parameters section's toolbar. Read up on the Optimize dialog, then enter
portfolio_nav(portfolio, to_date)
as your Objective function, set the date controls in the Test quotes box to coincide with the system's date range, make sure that Shuffle is unchecked and click Execute.
Given the simplicity of the system and the limited size of the parameter space to explore (11 x 11 = 121 combinations) it should take no more than a few minutes to find the best combination (to one decimal point) of _buy_fraction and _sell_fraction. Can you guess what it is?
Investment Studio comes with roughly 400 built-in functions for use in your expressions. Still, as your custom objects and systems grow more ambitious, you may eventually want to create your own functions. Investment Studio employs ActiveX Scripting to support custom functions. For historical reasons, such functions are known as "macro functions", or macros for short.
>>> Figures. The Macros view is the only one which we haven't visited yet. <<<
Indeed, the Macros view is where you tell Investment Studio which ActiveX Scripting engine it should use for macros and which macro packages it should load. It's also the place where you write and test new macros.
Can you guess what I'll ask you to read next?
>>> The overview of the Macros view. <<<
First, please read this introduction to macros. Then by all means proceed to the overview of the Macros view.
>>> Done. Please go on. <<<
OK, let's go through the creation of a simple macro. If you haven't already done so, please select the Macros view now.
I'll assume that Investment Studio is set up to use VBScript as its macro engine. This is the recommended choice, for a number of reasons: VBScript ships with Windows (so you can count on it being available pretty much on any PC capable of running Investment Studio), it's widely used, it's familiar to Microsoft Office macro writers, and (unlike e.g. JScript) it supports array passing.
If you have been experimenting with other scripting engines, use the combo box in the Macros view's upper left corner to switch back to VBScript before continuing.
Also, please understand that I will not try to teach you any programming. That's a huge subject in its own right; if you've never written a line of code before, there are countless books and online tutorials which will help get you started. All I want to show you here is the mechanics of getting a macro to work in Investment Studio.
>>> Understood. Would you mind getting on with it...? <<<
All right. First of all, we need a home for our new macro. I recommend creating any new macro in an otherwise empty macro package. This way, you can easily turn the new code on and off without affecting other macros. When it's ready, you can copy and paste it to a different location.
So, first step: right-click the list of macro packages to open its pop-up menu, then click New. This should cause a new package (aptly called "New") to be created. If nothing seems to happen, make sure that the list doesn't already contain a package called "New".
Select the new entry in the package list, make sure that it's not active (i.e. not checked) and click it again to open its in-place editor. Enter a descriptive name (I suggest "test") and close the in-place editor by pressing Enter.
Now turn your attention to the editor panel to the right. Note that the first tab is labeled with the name of the selected macro package, plus the filename extension associated with the VBScript engine (you did make sure that VBScript is selected, right?). If you've followed me so far, that should be "test.vbs". Make sure that this tab is selected. The editor panel is now displaying the contents of your new macro package.
>>> Looks empty to me. <<<
It is. New packages are created empty. Providing their content is up to you. I suggest that you enter the following code:
function my_add(a, b)
my_add = a + b
end function
|
This defines the macro my_add, which returns the sum of its two arguments (a and b).
>>> Done. <<<
Select a cell in the spreadsheet below the editor panel, then enter the expression
=my_add(1, 2)
in the edit box above the cell grid and press Enter. What do you see in the selected spreadsheet cell?
>>> #N/A <<<
That's the error code for "not available": the spreadsheet has no idea what "my_add" is. Which is understandable, since we haven't activated our new macro package yet. To do so...
>>> ... I mark its check-box in the package list. <<<
Eaxctly. Now what do you see in the cell?
>>> 3 <<<
Congratulations! Your new macro is functioning and can now be used in any expression throughout Investment Studio. If you click the editor panel tab labeled "Active macros", you will see its code along with the code of any other active macros.
By the way, don't worry about causing any damage in the "Active macros" page; it's read-only.
>>> So what is it good for? <<<
Several things. Seeing all the active macros together can be quite useful. While you're editing a macro, you may occasionally want to check which other macros it can call and with which arguments, or copy parts of other macros (or entire macros, when transferring them to a different package).
Perhaps most importantly, if a macro has a problem, the "All macros" page can help you locate the error.
>>> How? <<<
Switch back to our new macro's editor page and introduce an intentional error: in the second line, delete the "+" between "a" and "b". Then click the page's tab. This causes the change to be saved and the new code to be activated. What do you see in the spreadsheet?
>>> The #N/A error is back. <<<
A very versatile error code, that... Now look above the spreadsheet, at the editor panel's status bar. What does the last field say?
>>> "Can't parse script!" <<<
That means there is a syntax error in one of the active macros. Switch to the "Active macros" page. What do you see?
>>> The faulty line is selected, and the cursor is positioned in front of the "b", where the missing "+" should be. <<<
Handy, isn't it? Run-time errors can often be found this way, too. And they need not occur in the Macros view's spreadsheet, either. For instance, if you have been editing expressions containing macro calls in a Chart definition, and the Chart stops working, a look at the "All macros" page in the Macros view may tell you what's wrong.
Creating multiple user profiles
When you launch Investment Studio, it reads the file InvestmentStudio.INI in the start directory. This file lists the directories where the actual data files are located - things like user interface settings, quotes, portfolios and so on. You need only change this single file to have a completely different Investment Studio setup. So if you need to maintain different user profiles, for instance with different portfolios or different quote databases...
>>> ...I would maintain a separate version of InvestmentStudio.INI for each user profile. <<<
Right. You would create a bunch of directories, each one containing its own version of InvestmentStudio.INI. In order to run Investment Studio with a specific profile, you would simply start Investment Studio in the directory containing the InvestmentStudio.INI file for that profile.
>>> And how would I do that? <<<
The start directory for any application can be specified in the Properties dialog of the Windows shortcut used to launch the application. It doesn't matter whether the shortcut is located in the Start > Programs menu, on the Windows desktop or in a folder. The procedure is always the same: right-click the shortcut to open its Properties dialog and specify the full directory path in the dialog's "Start in" field.
>>> So for each user profile I would create a separate start directory containing a copy of InvestmentStudio.INI. I would also create a shortcut to Investment Studio and put the full path to the start directory in the "Start in" field of the shourtcut's Properties dialog. <<<
I couldn't have said it better myself.
>>> But how do I edit the file InvestmentStudio.INI? <<<
The best way is to start Investment Studio and then use its Directories dialog. By the way, the dialog is opened automatically at startup if a directory listed in InvestmentStudioINI is not found, or if a directory specification is missing altogether, so starting off a new user profile with an empty InvestmentStudio.INI will do, too. If you really, really know what you're doing, you can also edit InvestmentStudio.INI manually with a text editor (e.g. Windows NotePad).