Category Archives: Topical

Includes posts on physics, philosophy, sciences, quantitative finance, economics, environment etc.

Little Materialists

The other evening, I had a call from a headhunter. As I hung up, my six-year-old son walked in. So I asked him jokingly whether I should take another job. He asked,

“Does it mean you will get to come home earlier?”

I was mighty pleased that he liked to have me around at home, but I said,

“No, little fellow, I may have to work much longer hours. I will make a lot more money though. Do you think I should take it?”

I was certain that he would say, no, forget money, spend time at home. After all, he is quite close to me, and tries to hang out with me as much as he can. But, faced with this choice, he was quiet for a while. So I pressed him,

“Well, what do you think?”

To my dismay, he asked,

“How late?”

I decided to play along and said,

“I would probably get home only after you go to bed.”

He still seemed to hesitate. I persisted,

“Well, what do you think?”

My six-year-old said,

“If you have more money, you can buy me more stuff!”

Crestfallen as I was at this patently materialistic line of thinking (not to say anything about the blow to my parental ego), I had to get philosophical at this point. Why would a modern child value “stuff” more than his time with his parent?

I thought back about my younger days to imagine how I would have responded. I would have probably felt the same way. But then, this comparison is not quite fair. We were a lot poorer then, and my dad bringing in more money (and “stuff”) would have been nice. But lack of money has never been a reason for my not getting my kids the much sought after stuff of theirs. I could get them anything they could possibly want and then some. It is just that I have been trying to get them off “stuff” with environmental arguments. You know, with the help of Wall-E, and my threats that they will end up living in a world full of garbage. Clearly, it did not work.

May be we are not doing it right. We cannot expect our kids to do as we say, and not as we do. What is the use of telling them to value “stuff” less when we cannot stop dreaming of bigger houses and fancier cars? Perhaps the message of Wall-E loses a bit of its authenticity when played on the seventh DVD player and watched on the second big screen TV.

It is our materialism that is reflected in our kids’ priorities.

Blank Screen after Hibernate or Sleep?

Okay, the short answer, increase your virtual memory to more than the size of your physical memory.

Long version now. Recently, I had this problem with my PC that it wouldn’t wake up from hibernation or sleep mode properly. The PC itself would be on and churning, but the screen would switch to power save mode, staying blank. The only thing to do at that point would be to restart the computer.

Like the good netizen that I am, I trawled the Internet for a solution. But didn’t find any. Some suggested upgrading the BIOS, replacing the graphics card and so on. Then I saw this mentioned in a Linux group, saying that the size of the swap file should be more than the physical memory, and decided to try it on my Windows XP machine. And it solved the problem!

So the solution to this issue of blank screen after waking up is to set the size of the virtual memory to something larger than the memory in your system. If you need more information, here is how, in step-by-step form. These instructions apply to a Windows XP machine.

  1. Right-click on “My Computer” and hit “Properties.”
  2. Take a look at the RAM size, and click on the “Advanced” tab.
  3. Click on the “Setting” button under the “Performance” group box.
  4. In the “Performance Options” window that comes up, select the “Advanced” tab.
  5. In the “Virtual Memory” group box near the bottom, click on the “Change” button.
  6. In the “Virtual Memory” window that pops up, set the “Custom Size” to something more than your RAM size (that you saw in step 2). You can set it on any hard disk partition that you have, but if you are going through all these instructions, chances are you have only “C:”. In my case, I chose to put it on “M:”.

A New Kind of Binomial Tree

We can port even more complicated problems from mathematics directly to a functional language. For an example closer to home, let us consider a binomial pricing model, illustrating that the ease and elegance with which Haskell handles factorial do indeed extend to real-life quantitative finance problems as well.

The binomial tree pricing model works by assuming that the price of an underlying asset can only move up or down by constant factors u and d during a small time interval \delta t. Stringing together many such time intervals, we make up the expiration time of the derivative instrument we are trying to price. The derivative defined as a function of the price of the underlying at any point in time.

Figure 1
Figure 1. Binomial tree pricing model. On the X axis, labeled i, we have the time steps. The Y axis represents the price of the underlying, labeled j. The only difference from the standard binomial tree is that we have let j be both positive and negative, which is mathematically natural, and hence simplifies the notation in a functional language.

We can visualize the binomial tree as shown in Fig. 1. At time t = 0, we have the asset price S(0) = S_0. At t = \delta t (with the maturity T = N\delta t). we have two possible asset values S_0 u and S_0 d = S_0 / u, where we have chosen d = 1/u. In general, at time i\delta t, at the asset price node level j, we have

S_{ij} = S_0 u^j

By choosing the sizes of the up and down price movements the same, we have created a recombinant binomial tree, which is why we have only 2i+1 price nodes at any time step i\delta t. In order to price the derivative, we have to assign risk-neutral probabilities to the up and down price movements. The risk-neutral probability for an upward movement of u is denoted by p. With these notations, we can write down the fair value of an American call option (of expiry T, underlying asset price S_0, strike price K, risk free interest rate r, asset price volatility \sigma and number of time steps in the binomial tree N) using the binomial tree pricing model as follows:

\textrm{OptionPrice}(T, S_0, K, r, \sigma, N) = f_{00}

where f_{ij} denotes the fair value of the option at any the node i in time and j in price (referring to Fig. 1).

f_{ij} = \left{\begin{array}{ll}\textrm{Max}(S_{ij} - K, 0) & \textrm{if } i = N \\textrm{Max}(S_{ij} - 0, e^{-\delta tr}\left(p f_{i+1, j+1} + (1-p)  f_{i+1, j-1}\right)) & \textrm {otherwise}\end{array}\right

At maturity, i = N and i\delta t = T, where we exercise the option if it is in the money, which is what the first Max function denotes. The last term in the express above represents the risk neutral backward propagation of the option price from the time layer at (i+1)\delta t to i\delta t. At each node, if the option price is less than the intrinsic value, we exercise the option, which is the second Max function.

The common choice for the upward price movement depends on the volatility of the underlying asset. u = e^{\sigma\sqrt{\delta t}} and the downward movement is chosen to be the same d = 1/u to ensure that we have a recombinant tree. For risk neutrality, we have the probability defined as:

p = \frac{ e^{r\delta t} - d}{u - d}

For the purpose of illustrating how it translates to the functional programming language of Haskell, let us put all these equations together once more.

\textrm{OptionPrice}(T, S_0, K, r, \sigma, N) = f_{00}
where
&f_{ij}  =& \left\{\begin{array}{ll}\textrm{Max}(S_{ij} - K, 0) & \textrm{if } i = N \\\textrm{Max}(S_{ij} - 0, e^{-\delta tr}\left(p f_{i+1\, j+1} + (1-p)  f_{i+1\, j-1}\right)\quad \quad& \textrm{otherwise}\end{array}\right.
S_{ij}  = S_0 u^j
u = e^{\sigma\sqrt{\delta t}}
d  = 1/u
\delta t  = T/N
p  = \frac{ e^{r\delta t} - d}{u - d}

Now, let us look at the code in Haskell.

optionPrice t s0 k r sigma n = f 0 0
    where
      f i j =
          if i == n
          then max ((s i j) - k) 0
          else max ((s i j) - k)
                    (exp(-r*dt) * (p * f(i+1)(j+1) +
                    (1-p) * f(i+1)(j-1)))
      s i j = s0 * u**j
      u = exp(sigma * sqrt dt)
      d = 1 / u
      dt = t / n
      p = (exp(r*dt)-d) / (u-d)

As we can see, it is a near-verbatim rendition of the mathematical statements, nothing more. This code snippet actually runs as it is, and produces the result.

*Main> optionPrice 1 100 110 0.05 0.3 20
10.10369526959085

Looking at the remarkable similarity between the mathematical equations and the code in Haskell, we can understand why mathematicians love the idea of functional programming. This particular implementation of the binomial pricing model may not be the most computationally efficient, but it certainly is one of great elegance and brevity.

While a functional programming language may not be appropriate for a full-fledged implementation of a trading platform, many of its underlying principles, such as type abstractions and strict purity, may prove invaluable in programs we use in quantitative finance where heavy mathematics and number crunching are involved. The mathematical rigor enables us to employ complex functional manipulations at the program level. The religious adherence to the notion of statelessness in functional programming has another great benefit. It helps in parallel and grid enabling the computations with almost no extra work.

Sections

Functional Programming

Functional programming is the programming methodology that puts great emphasis on statelessness and religiously avoids side effects of one function in the evaluation any other function. Functions in this methodology are like mathematical functions. The conventional programming style, on the other hand, is considered “imperative” and uses states and their changes for accomplishing computing tasks.

Adapting this notion of functional programming may sound like regressing back to the pre-object-oriented age, and sacrificing all the advantages thereof. But there are practitioners, both in academia and in the industry, who strongly believe that functional languages are the only approach that ensures stability and robustness in financial and number crunching applications.

Functional languages, by definition, are stateless. They do everything through functions, which return results that are, well, functions of their arguments. This statelessness immediately makes the functions behave like their mathematical counterparts. Similarly, in a functional language, variable behave like mathematical variables rather than labels for memory locations. And a statement like x = x + 1 would make no sense. After all, it makes no sense in real life either.

This strong mathematical underpinning makes functional programming the darling of mathematicians. A piece of code written in a functional programming language is a set of declarations quite unlike a standard computer language such as C or C++, where the code represents a series of instructions for the computer. In other words, a functional language is declarative — its statements are mathematical declarations of facts and relationships, which is another reason why a statement like x = x + 1 would be illegal.

The declarative nature of the language makes it “lazy,” meaning that it computes a result only when we ask for it. (At least, that is the principle. In real life, full computational laziness may be difficult to achieve.) Computational laziness makes a functional programming language capable of handling many situations that would be impossible or exceedingly difficult for procedural languages. Users of Mathematica, which is a functional language for symbolic manipulation of mathematical equations, would immediately appreciate the advantages of computational laziness and other functional features such as its declarative nature. In Mathematica, we can carry out an operation like solving an equation for instance. Once that is done, we can add a few more constraints at the bottom of our notebook, scroll up to the command to solve the original equation and re-execute it, fully expecting the later constraints to be respected. They will be, because a statement appearing at a later part in the program listing is not some instruction to be carried out at a later point in a sequence. It is merely a mathematical declaration of truism, no matter where it appears.

This affinity of functional languages toward mathematics may appeal to quants as well, who are, after all, mathematicians of the applied kind. To see where the appeal stems from, let us consider a simple example of computing the factorial of an integer. In C or C++, we can write a factorial function either using a loop or making use of recursion. In a functional language, on the other hand, we merely restate the mathematical definition, using the syntax of the language we are working with. In mathematics, we define factorial as:

n! = left{begin{array}{ll}1 & n=1 \n times (n-1)! & textrm{Otherwise}end{array}right.

And in Haskell (a well known functional programming language), we can write:

bang 1 = 1
bang n = n * bang (n-1)

And expect to make the call bang 12 to get the factorial of 12.

This example may look artificially simple. But we can port even more complicated problems from mathematics directly to a functional language. For an example closer to home, let us consider a binomial pricing model, illustrating that the ease and elegance with which Haskell handles factorial do indeed extend to real-life quantitative finance problems as well.

Sections

Magic of Object Oriented Languages

Nowhere is the dominance of paradigms more obvious than in object oriented languages. Just take a look at the words that we use to describe some their features: polymorphism, inheritance, virtual, abstract, overloading — all of them normal (or near-normal) everyday words, but signifying notions and concepts quite far from their literal meaning. Yet, and here is the rub, their meaning in the computing context seems exquisitely appropriate. Is it a sign that we have taken these paradigms too far? Perhaps. After all, the “object” in object oriented programming is already an abstract paradigm, having nothing to do with “That Obscure Object of Desire,” for instance.

We do see the abstraction process running a bit wild in design patterns. When a pattern calls itself a visitor or a factory, it takes a geekily forgiving heart to grant the poetic license silently usurped. Design patterns, despite the liberties they take with our sensitivities, add enormous power to object oriented programming, which is already very powerful, with all the built in features like polymorphism, inheritance, overloading etc.

To someone with an exclusive background in sequential programming, all these features of object oriented languages may seem like pure magic. But most of the features are really extensions or variations on their sequential programming equivalents. A class is merely a structure, and can even be declared as such in C++. When you add a method in a class, you can imagine that the compiler is secretly adding a global function with an extra argument (the reference to the object) and a unique identifier (say, a hash value of the class name). Polymorphic functions also can be implemented by adding a hash value of the function signature to the function names, and putting them in the global scope.

The real value of the object oriented methodology is that it encourages good design. But good programming discipline goes beyond mere adaptation of an object oriented language, which is why my first C++ teacher said, “You can write bad Fortran in C++ if you really want. Just that you have to work a little harder to do it.”

For all their magical powers, the object oriented programming languages all suffer from some common weaknesses. One of their major disadvantages is, in fact, one of the basic design features of object oriented programming. Objects are memory locations containing data as laid down by the programmer (and the computer). Memory locations remember the state of the object — by design. What state an object is in determines what it does when a method is invoked. So object oriented approach is inherently stateful, if we can agree on what “state” means in the object oriented context.

But in a user interface, where we do not have much control over the sequence in which various steps are executed, we might get erroneous results in stateful programming depending on what step gets executed at a what point in time. Such considerations are especially important when we work with parallel computers in complex situations. One desirable property in such cases is that the functions return a number solely based on their arguments. This property, termed “purity,” is the basic design goal of most functional languages, although their architects will concede that most of them are not strictly “pure.”

Sections

Paradigms All the Way

Paradigms permeate almost all aspects of computing. Some of these paradigms are natural. For instance, it is natural to talk about an image or a song when we actually mean a JPEG or an MP3 file. File is already an abstraction evolved in the file-folder paradigm popularized in Windows systems. The underlying objects or streams are again abstractions for patterns of ones and zeros, which represent voltage levels in transistors, or spin states on a magnetic disk. There is an endless hierarchy of paradigms. Like the proverbial turtles that confounded Bertrand Russell (or was it Samuel Johnson?), it is paradigms all the way down.

Some paradigms have faded into the background although the terminology evolved from them lingers. The original paradigm for computer networks (and of the Internet) was a mesh of interconnections residing in the sky above. This view is more or less replaced by the World Wide Web residing on the ground at our level. But we still use the original paradigm whenever we say “download” or “upload.” The World Wide Web, by the way, is represented by the acronym WWW that figures in the name of all web sites. It is an acronym with the dubious distinction of being about the only one that takes us longer to say than what it stands for. But, getting back to our topic, paradigms are powerful and useful means to guide our interactions with unfamiliar systems and environments, especially in computers, which are strange and complicated beasts to begin with.

A basic computer processor is deceptively simple. It is a string of gates. A gate is a switch (more or less) made up of a small group of transistors. A 32 bit processor has 32 switches in an array. Each switch can be either off representing a zero, or on (one). And a processor can do only one function — add the contents of another array of gates (called a register) to itself. In other words, it can only “accumulate.”

In writing this last sentence, I have already started a process of abstraction. I wrote “contents,” thinking of the register as a container holding numbers. It is the power of multiple levels of abstraction, each of which is simple and obvious, but building on whatever comes before it, that makes a computer enormously powerful.

We can see abstractions, followed by the modularization of the abstracted concept, in every aspect of computing, both hardware and software. Groups of transistors become arrays of gates, and then processors, registers, cache or memory. Accumulations (additions) become all arithmetic operations, string manipulations, user interfaces, image and video editing and so on.

Another feature of computing that aids in the seemingly endless march of the Moore’s Law (which states that computers will double in their power every 18 months) is that each advance seems to fuel further advances, generating an explosive growth. The first compiler, for instance, was written in the primitive assembler level language. The second one was written using the first one and so on. Even in hardware development, one generation of computers become the tools in designing the next generation, stoking a seemingly inexorable cycle of development.

While this positive feedback in hardware and software is a good thing, the explosive nature of growth may take us in wrong directions, much like the strong grown in the credit market led to the banking collapses of 2008. Many computing experts now wonder whether the object oriented technology has been overplayed.

Sections

Zeros and Ones

Computers are notorious for their infuriatingly literal obedience. I am sure anyone who has ever worked with a computer has come across the lack of empathy on its part — it follows our instructions to the dot, yet ends up accomplishing something altogether different from what we intend. We have all been bitten in the rear end by this literal adherence to logic at the expense of commonsense. We can attribute at least some of the blame to our lack of understanding (yes, literal and complete understanding) of the paradigms used in computing.

Rich in paradigms, the field of computing has a strong influence in the way we think and view the world. If you don’t believe me, just look at the way we learn things these days. Do we learn anything now, or do we merely learn how to access information through browsing and searching? Even our arithmetic abilities have eroded along with the advent of calculators and spreadsheets. I remember the legends of great minds like Enrico Fermi, who estimated the power output of the first nuclear blast by floating a few pieces of scrap paper, and like Richard Feynman, who beat an abacus expert by doing binomial expansion. I wonder if the Fermis and Feynmans of our age would be able to pull those stunts without pulling out their pocket calculators.

Procedural programming, through its unwarranted reuse of mathematical symbols and patterns, has shaped the way we interact with our computers. The paradigm that has evolved is distinctly unmathematical. Functional programming represents a counter attack, a campaign to win our minds back from the damaging influences of the mathematical monstrosities of procedural languages. The success of this battle may depend more on might and momentum rather than truth and beauty. In our neck of the woods, this statement translates to a simple question: Can we find enough developers who can do functional programming? Or is it cheaper and more efficient to stick to procedural and object oriented methodologies?

Sections

Change the Facts

There is beauty in truth, and truth in beauty. Where does this link between truth and beauty come from? Of course, beauty is subjective, and truth is objective — or so we are told. It may be that we have evolved in accordance with the beautiful Darwinian principles to see perfection in absolute truth.

The beauty and perfection I’m thinking about are of a different kind — those of ideas and concepts. At times, you may get an idea so perfect and beautiful that you know it has to be true. This conviction of truth arising from beauty may be what made Einstein declare:

But this conviction about the veracity of a theory based on its perfection is hardly enough. Einstein’s genius really is in his philosophical tenacity, his willingness to push the idea beyond what is considered logical.

Let’s take an example. Let’s say you are in a cruising airplane. If you close the windows and somehow block out the engine noise, it will be impossible for you to tell whether you are moving or not. This inability, when translated to physics jargon, becomes a principle stating, “Physical laws are independent of the state of motion of the experimental system.”

The physical laws Einstein chose to look at were Maxwell’s equations of electromagnetism, which had the speed of light appearing in them. For them to be independent of (or covariant with, to be more precise) motion, Einstein postulated that the speed of light had to be a constant regardless of whether you were going toward it or away from it.

Now, I don’t know if you find that postulate particularly beautiful. But Einstein did, and decided to push it through all its illogical consequences. For it to be true, space has to contract and time had to dilate, and nothing could go faster than light. Einstein said, well, so be it. That is the philosophical conviction and tenacity that I wanted to talk about — the kind that gave us Special Relativity about a one hundred years ago.

Want to get to General Relativity from here? Simple, just find another beautiful truth. Here is one… If you have gone to Magic Mountain, you would know that you are weightless during a free fall (best tried on an empty stomach). Free fall is acceleration at 9.8 m/s/s (or 32 ft/s/s), and it nullifies gravity. So gravity is the same as acceleration — voila, another beautiful principle.

World line of airplanesIn order to make use of this principle, Einstein perhaps thought of it in pictures. What does acceleration mean? It is how fast the speed of something is changing. And what is speed? Think of something moving in a straight line — our cruising airplane, for instance, and call the line of flight the X-axis. We can visualize its speed by thinking of a time T-axis at right angles with the X-axis so that at time = 0, the airplane is at x = 0. At time t, it is at a point x = v.t, if it is moving with a speed v. So a line in the X-T plane (called the world line) represents the motion of the airplane. A faster airplane would have a shallower world line. An accelerating airplane, therefore, will have a curved world line, running from the slow world line to the fast one.

So acceleration is curvature in space-time. And so is gravity, being nothing but acceleration. (I can see my physicist friends cringe a bit, but it is essentially true — just that you straighten the world-line calling it a geodesic and attribute the curvature to space-time instead.)

The exact nature of the curvature and how to compute it, though beautiful in their own right, are mere details, as Einstein himself would have put it. After all, he wanted to know God’s thoughts, not the details.

Of Dreams and Memories

I recently watched The Diving Bell and the Butterfly (Le scaphandre et le papillon), which describes the tragic plight of the French journalist Jean-Dominique Bauby, who suffered a severe stroke and became “locked-in.” During my research days, I had worked a bit on rehabilitation systems for such locked-in patients, who have normal or near-normal cognitive activities but no motor control. In other words, their fully functional minds are locked in a useless body that affords them no means of communication with the external world. It is the solitary confinement of the highest order.

Locked-in condition is one of my secret fears; not so much for myself, but that someone close to me might have to go through it. My father suffered a stroke and was comatose for a month before he passed away, and I will always wonder whether he was locked-in. Did he feel pain and fear? So I Googled a bit to find out if stroke patients were conscious inside. I couldn’t find anything definitive. Then it occurred to me that perhaps these stroke patients were conscious, but didn’t remember it later on.

That thought brought me to one of my philosophical musings. What does it mean to say that something happened if you cannot remember it? Let’s say you had to go through a lot of pain for whatever reason. But you don’t remember it later. Did you really suffer? It is like a dream that you cannot remember. Did you really dream it?

Memory is an essential ingredient of reality, and of existence — which is probably why they can sell so many digital cameras and camcorders. When memories of good times fade in our busy minds, perhaps we feel bits of our existence melting away. So we take thousands of pictures and videos that we are too busy to look at later on.

But I wonder. When I die, my memories will die with me. Sure, those who are close to me will remember me for a while, but the memories that I hold on to right now, the things I have seen and experienced, will all disappear — like an uncertain dream that someone (perhaps a butterfly) dreamt and forgot. So what does it mean to say that I exist? Isn’t it all a dream?

How to save a string to a local file in PHP?

This post is the second one in my geek series.

While programming my Theme Tweaker, I came across this problem. I had a string on my server in my php program (the tweaked stylesheet, in fact), and I wanted to give the user the option of saving it to a file his computer. I would’ve thought this was a common problem, and all common problems can be solved by Googling. But, lo and behold, I just couldn’t find a satisfactory solution. I found my own, and thought I would share it here, for the benefit of all the future Googlers yet to come and go.

Before we go into the solution, let’s understand what the problem is. The problem is in the division of labor between two computers — one is the server, where your WordPress and PHP are running; the other is the client’s computer where the viewing is taking place. The string we are talking about is on the server. We want to save it in a file on the client’s computer. The only way to do it is by serving the string as an html reply.

At first glance, this doesn’t look like a major problem. After all, servers regularly send strings and data to clients — that’s how we see anything on the the browser, including what you are reading. If it was just any PHP program that wants to save the string, it wouldn’t be a problem. You could just dump the string into a file on the server and serve the file.

But what do you do if you don’t want to give the whole world a way of dumping strings to files on your server? Well, you could do something like this:

<?php
header('Content-Disposition: attachment; filename="style.css"');
header("Content-Transfer-Encoding: ascii");
header('Expires: 0');
header('Pragma: no-cache');
print $stylestr ;
?>

So, just put this code in your foo.php that computes the string $stylestr and you are done. But our trouble is that we are working in the WordPress plugin framework, and cannot use the header() calls. When you try to do that, you will get the error message saying that header is already done dude. For this problem, I found the ingenious solution in one of the plugins that I use. Forgot which one, but I guess it is a common technique. The solution is to define an empty iFrame and set its source to what the PHP function would write. Since iFrame expects a full HTML source, you are allowed (in fact, obliged) to give the header() directives. The code snippet looks something like:

<iframe id="saveCSS" src="about:blank" style="visibility:hidden;border:none;height:1em;width:1px;"></iframe>
<script type="text/javascript">
var fram = document.getElementById("saveCSS");
<?php echo 'fram.src = "' . $styleurl .'"' ;
?>

Now the question is, what should the source be? In other words, what is $styleurl? Clearly, it is not going to be a static file on your server. And the purpose of this post is to show that it doesn’t have to be a file on the server at all. It is a two-part answer. You have to remember that you are working within the WordPress framework, and you cannot make standalone php files. The only thing you can do is to add arguments to the existing php files, or the plugins you have created. So you first make a submit button as follows:

<form method="post" action="<?php echo $_SERVER["REQUEST_URI"]?>">
<div class="submit">
<input type="submit" name="saveCSS" title="Download the tweaked stylesheet to your computer" value="Download Stylesheet" />
</div>

Note that the name attribute of the button is “saveCSS.” Now, in the part of the code that handles submits, you do something like:

<?php
if (isset($_POST['saveCSS']))
$styleurl = get_option('siteurl') . '/' . "/wp-admin/themes.php?page=theme-tweaker.php&save" ;

?>

This is the $styleurl that you would give as the source of your iFrame, fram. Note that it is the same as your pluging page URL, except that you managed to add “?save” at the end of it. The next trick is to capture that argument and handle it. For that, you use the WordPress API function, add_action as:

<?php
if (isset($_GET['save'] ))
add_action('init', array(&$thmTwk, 'saveCSS'));
else
remove_action('init', array(&$thmTwk, 'saveCSS'));
?>

This adds a function saveCSS to the init part of your plugin. Now you have to define this function:

<?php
function saveCSS() {
header('Content-Disposition: attachment; filename="style.css"');
header("Content-Transfer-Encoding: ascii");
header('Expires: 0');
header('Pragma: no-cache');
$stylestr = "Whatever string you want to save";
ob_start() ;
print $stylestr ;
ob_end_flush() ;
die() ;
}
?>

Now we are almost home free. The only thing to understand is that you do need the die(). If your function doesn’t die, it will spew out the rest of the WordPress generated stuff into your save file, appending it to your string $stylestr.

It may look complicated. Well, I guess it is a bit complicated, but once you implement it and get it running, you can (and do) forget about it. At least, I do. That’s why I posted it here, so that the next time I need to do it, I can look it up.