<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[FinDev]]></title><description><![CDATA[Notes about financial software development]]></description><link>https://findev.datainquiry.dev</link><generator>RSS for Node</generator><lastBuildDate>Tue, 14 Apr 2026 02:43:17 GMT</lastBuildDate><atom:link href="https://findev.datainquiry.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Obtaining Data via API]]></title><description><![CDATA[I recently worked on an integration to fetch weather data by accessing the National Weather Service (NWS) API. At first glance, this task usually seems as simple as sending an HTTP request to the server and receiving the data. However, the process is...]]></description><link>https://findev.datainquiry.dev/obtaining-data-via-api</link><guid isPermaLink="true">https://findev.datainquiry.dev/obtaining-data-via-api</guid><category><![CDATA[APIs]]></category><category><![CDATA[Data access]]></category><dc:creator><![CDATA[Jaime Lopez]]></dc:creator><pubDate>Wed, 03 Dec 2025 21:53:36 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1764798639314/8f0df5fb-fe22-444a-8ef6-c6da60871974.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I recently worked on an integration to fetch weather data by accessing the National Weather Service (NWS) API. At first glance, this task usually seems as simple as sending an HTTP request to the server and receiving the data. However, the process is more complex than it appears. I started with just a couple of instructions and ended up with more than 1,200 lines of code, including tests. From this experience, I describe below some of the lessons I learned.</p>
<p>Initially, the task can be thought of as running <code>curl</code> from the command line, making a <code>fetch</code> call in JavaScript, or using <code>requests.get</code> in Python. But as you dig into the details, you uncover multiple considerations related to preparing the request, maintaining the connection, handling authentication, managing errors, respecting API limits, processing the response, storing the data, and integrating with the existing system.</p>
<p>The API documentation is essential and should be read carefully. In my work with the NWS API, I identified requirements such as including identification headers in every request, the different endpoints where the data I needed was available, the formats of requests and responses, and the usage limits I had to respect to avoid being blocked.</p>
<p>Defining appropriate data structures for requests and responses is crucial—not only to ensure effective interaction with the API but also to guarantee the correct processing of the data and proper integration with the existing system. In my case, since the implementation was in Python, I used <code>dataclasses</code> as arguments and return values in most functions. I also included helper functions to handle conversions between data types, such as time representations. This made validation and manipulation of data easier, facilitated error detection, and greatly improved code readability.</p>
<p>Rather than thinking of API requests as isolated actions, it is more effective to treat them as a comprehensive process that involves multiple safeguards and checks. It helps to anticipate from the start that a request may fail and to mitigate the associated risks. In my project, I had to include timeouts, retries, delays between requests, rate limiting, HTTP error handlers, response caching, and session persistence.</p>
<p>A test-driven development (TDD) approach is valuable for ensuring code quality and reliability. As shown in the previous paragraphs, API integration can be quite complex. Unit and integration tests help identify errors, maintain code stability, and facilitate changes. Although labor-intensive, writing automated tests from the early stages of development helped me a lot. There were moments when some changes seemed to break important parts of the code, but the tests helped me quickly identify and fix the issues.</p>
<p>One aspect I now value more is the traceability of the data-retrieval process. Detailed logging and the tracking of usage metrics are extremely helpful. This not only enables real-time observation of how the code behaves, but also supports later analysis to identify unnoticed failures, bottlenecks, and improvement opportunities. In my project, Python’s <code>logging</code> module proved invaluable.</p>
<p>Although in the example I mentioned performance was not a critical factor, in other scenarios it may well be. In general, API access involves inherent network latency that little can be done about. However, good connection management, correct request preparation, and efficient response handling can significantly improve performance. For instance, being able to recover data in the middle of a problematic session is more efficient than declaring the request failed and restarting it from scratch. Moreover, with proper planning and synchronization, waiting times can be used to perform other tasks, such as processing previously received data or exchanging information with other components of the system.</p>
<p>As with any engineering work, it is in the details where a robust and reliable product is defined. Integration with an API through network communication is a critical component of today’s interconnected systems. If you take the opportunity to work carefully through each of these details, the final result will be a solid system that satisfies users—and for developers, an experience that brings peace of mind and confidence in the work done.</p>
]]></content:encoded></item><item><title><![CDATA[Priority Queues]]></title><description><![CDATA[There are many cases where maintaining a priority-based queue is essential. For instance, it may be required to rebalance a financial portfolio by reallocating assets with the highest deviation first. Another example is ranking updates when processin...]]></description><link>https://findev.datainquiry.dev/priority-queues-zig</link><guid isPermaLink="true">https://findev.datainquiry.dev/priority-queues-zig</guid><category><![CDATA[zig]]></category><category><![CDATA[queue]]></category><category><![CDATA[priority queue]]></category><dc:creator><![CDATA[Jaime Lopez]]></dc:creator><pubDate>Mon, 24 Mar 2025 18:32:02 GMT</pubDate><content:encoded><![CDATA[<p>There are many cases where maintaining a priority-based queue is essential. For instance, it may be required to rebalance a financial portfolio by reallocating assets with the highest deviation first. Another example is ranking updates when processing asynchronous market data, where prioritization is critical. This note explains what a priority queue is and provides an efficient implementation in Zig.</p>
<h2 id="heading-priority-queue">Priority Queue</h2>
<p>In a basic queue, elements are appended to the tail and removed from the front, following a first-in, first-out (FIFO) order. This means the first element to arrive is the first to leave. The primary operations of a queue are:</p>
<ul>
<li><code>enqueue</code>:  append a new element to the tail of the queue</li>
<li><code>dequeue</code>: remove the older element from the head of queue</li>
<li><code>peek</code>: query the value of the element located at the head of the queue</li>
</ul>
<p>In a priority queue, each element has an associated priority level. The priority can be represented as an enumeration (e.g., high, medium, low), an integer (with higher values indicating higher priority), or a real number (e.g., price), among other ordering schemes.</p>
<p>Elements in a priority queue are sorted by priority and time of arrival. When a new element is added, it is positioned behind the last element with the same priority. The element at the head of the queue is the oldest one with the highest priority.</p>
<p>Unlike a basic queue, a priority queue requires a sorting algorithm when inserting a new element. Some implementations may also require a search algorithm to extract the highest-priority element. In the next section, a priority queue is implemented using the insertion sort algorithm for enqueueing new elements.</p>
<h2 id="heading-a-zigs-implementation">A Zig's implementation</h2>
<p>This section presents a priority queue implementation in Zig, a programming language well-suited for performance-critical applications. Zig’s manual memory management ensures efficient, fine-grained, and predictable allocations. Additionally, its low-latency and cache-efficient data structures make it ideal for real-time applications.</p>
<p>This implementation is based on a generic data type and avoids heap memory allocations. It uses two arrays—one for storing elements and another for storing priorities. These arrays are accessed as a circular list using two indices: <code>head</code> and <code>tail</code>. The <code>enqueue</code> operation runs in \(O(n)\) time, while <code>dequeue</code> and <code>peek</code> execute in \(O(1)\) time.</p>
<p>To provide a generic implementation, a function is defined that takes the type <code>T</code>, an example value of type <code>T</code>, and the queue length as arguments. For example, calling <code>PriorityCircularQueue(u32, 0, 128)</code> defines a queue for unsigned integers with a capacity of 128 elements. Additionally, an error enumeration is included to indicate when the queue is empty or full.</p>
<pre><code class="lang-zig">pub const QueueError = error {
    Full,
    Empty,
};

pub fn PriorityCircularQueue(
    T: type,
    example_value: T,
    len: usize
) type {
    return struct {
        ...
    };
}
</code></pre>
<p>The attributes of this struct are shown below. It has two arrays: <code>items</code> for storing elements and <code>priorities</code> for storing priority values. The <code>len</code> attribute represents the number of elements in the queue, while <code>size</code> defines the queue's capacity. The queue’s front and rear are represented by <code>head</code> and <code>tail</code>.</p>
<pre><code class="lang-zig">struct {
        items: [size]T = [_]T{example_value} ** size,
        priorities: [size]u8 = [_]u8{0} ** size,
        size: usize = size,
        len: usize = 0,
        head: usize = 0,
        tail: usize = size,
        ...
};
</code></pre>
<p>To indicate that the queue is empty, a special flag is used with <code>tail == size</code>. If the queue is not empty, <code>tail</code> will have a value between <code>0</code> and <code>size - 1</code>, inclusive.</p>
<p>The simplest operation is <code>peek</code>, which only needs to check if the queue is not empty before returning the value at the queue’s head. The <code>dequeue</code> operation is similar to <code>peek</code>, but before returning the value, moves <code>head</code> to the next position. If no more elements remain in the queue, <code>tail</code> is set to <code>size</code>. As mentioned earlier, both operations run in \(O(1)\) time and work the same way in both priority and basic circular queues.</p>
<pre><code class="lang-zig">pub fn peek(self: @This()) !T {
    if (self.tail == self.size) {
        return QueueError.Empty;
    }
    return self.items[self.head];
}

pub fn dequeue(self: *@This()) !T {
    if (self.tail == self.size) {
        return QueueError.Empty;
    }
    const curr = self.head;
    self.head = (self.head + 1) % self.size;
    if (self.head == self.tail) {
        // Set the queue as empty
        self.tail = self.size;
    }
    self.len -= 1;
    return self.items[curr];
}
</code></pre>
<p>As first action, <code>enqueue</code> appends the new element at the tail of the queue, the same as a basic queue. It also stores the priority of the new element, using the same position as in the <code>items</code> array. However, to be priority queue, the new element has to be moved from the tail if it has a higher priority. It has to be inserted behind the last element with the same priority. Below, the definition of <code>enqueue</code> is presented, except for the sorting operation, that at this moment has been indicated only with a comment.</p>
<pre><code class="lang-zig">pub fn enqueue(
    self: *@This(),
    item: T,
    priority: u8
) !void {
    if (self.tail == self.head) {
        return QueueError.Full;                
    }
    if (self.tail == self.size) {
        // The queue is empty, so let's
        // start filling it
        self.tail = self.head;
    }
    self.items[self.tail] = item;
    self.priorities[self.tail] = priority;

    // TODO: Sorting by priority

    self.len += 1;
    self.tail = (self.tail + 1) % self.size;
}
</code></pre>
<p>In this example, the insertion sort algorithm is used to maintain the correct order in the <code>priorities</code> array. The first step is to iterate through the queue, starting from the head, to determine the correct position for the new element based on its priority. Once identified, all elements after that position are shifted to make space for the new element. This algorithm has \(O(n)\) execution time. For small queue sizes, this approach may be optimal, but for larger sizes, a more efficient sorting algorithm should be considered.</p>
<pre><code class="lang-zig">var curr = self.head;
var move_to = self.tail;

while (curr != self.tail) {
    if (self.priorities[self.tail] &gt; self.priorities[curr]) {
        move_to = curr;
        break;
    }
    curr = (curr + 1) % self.size;
}

while (move_to != self.tail) {
    std.mem.swap(
        T,
        &amp;self.items[self.tail],
        &amp;self.items[move_to]
    );
    std.mem.swap(
        u8,
        &amp;self.priorities[self.tail],
        &amp;self.priorities[move_to]
    );
    move_to = (move_to + 1) % self.size;
}
</code></pre>
<p>In summary, this implementation of a priority queue in Zig demonstrates how to efficiently manage prioritized elements using a circular buffer and insertion sort. While this approach provides \(O(1)\) performance for <code>peek</code> and <code>dequeue</code>, the \(O(n)\) complexity of <code>enqueue</code> may become a bottleneck for larger queues. In such cases, more advanced data structures like binary heaps or balanced trees could be considered to optimize performance. Nonetheless, this implementation serves as a solid foundation for real-time applications that require fine-grained control over memory and execution speed.</p>
<p><a target="_blank" href="https://gist.github.com/jailop/0dc186ee4f870b55f1ced5148d3d4d07">Source code</a></p>
]]></content:encoded></item><item><title><![CDATA[Cronbach's Alpha]]></title><description><![CDATA[In a survey questionnaire, a set of items referred to the same construct or concept is included. Therefore, it is expected that responses for those items are similar or highly correlated. To measure that, the Cronbach’s Alpha is frequently used. It e...]]></description><link>https://findev.datainquiry.dev/cronbachs-alpha</link><guid isPermaLink="true">https://findev.datainquiry.dev/cronbachs-alpha</guid><category><![CDATA[cronbach]]></category><category><![CDATA[alpha]]></category><category><![CDATA[Rust]]></category><dc:creator><![CDATA[Jaime Lopez]]></dc:creator><pubDate>Sat, 15 Mar 2025 18:12:17 GMT</pubDate><content:encoded><![CDATA[<p>In a survey questionnaire, a set of items referred to the same construct or concept is included. Therefore, it is expected that responses for those items are similar or highly correlated. To measure that, the Cronbach’s Alpha is frequently used. It estimates the reliability or the internal consistency for a set of survey items.</p>
<p>A set of related survey items can be like these ones:</p>
<ol>
<li>My claim was attended in a reasonable amount of time.</li>
<li>I am satisfied with the timeliness of the service.</li>
<li>The time I waited for services was acceptable.</li>
<li>I am satisfied with the services I received.</li>
</ol>
<p>The Cronbach’s Alpha is expressed as a point generally in the interval between 0 and 1. It is asumed that greater values represent a higher internal consistency. As a rule of thumb, obtaining a value higher than 0.7 is an acceptable result. The formula to calculate the Cronbach’s Alpha is shown below.</p>
<p>$$\alpha = \frac{n}{n - 1} (1 - \frac{\sum_{i=1}^n \sigma_i^2}{\sigma_T^2})$$</p><p>Where:</p>
<p>\(n\): the number of items<br />\(\sigma_i^2\): variance in responses for an individual item<br />\(\sigma_T^2\): variance of total scores for all the items</p>
<p>The reasoning behind the Cronbach's Alpha is that responses for each item should have a lower fluctuation, \(\sigma_i^2\). Instead, the total variance among items \(\sigma_T^2\) should be higher. Therefore, the quotient of the aggregated variance for individual items over the variance of total scores for all the items is expected to be a small number. To obtain the estimation, that number is subtracted from 1 and adjusted by \(\frac{n}{n - 1}\). This final adjustment is to prevent an underestimation when there are few items.</p>
<h2 id="heading-implementation">Implementation</h2>
<p>A Python's quick implementation can be the next one:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np

<span class="hljs-comment"># Rows are respondents</span>
<span class="hljs-comment"># Columns are survey items</span>
data = np.array([
    [<span class="hljs-number">4.0</span>, <span class="hljs-number">4.0</span>, <span class="hljs-number">4.0</span>, <span class="hljs-number">5.0</span>],
    [<span class="hljs-number">3.0</span>, <span class="hljs-number">4.0</span>, <span class="hljs-number">3.0</span>, <span class="hljs-number">4.0</span>],
    [<span class="hljs-number">5.0</span>, <span class="hljs-number">4.0</span>, <span class="hljs-number">5.0</span>, <span class="hljs-number">5.0</span>],
    [<span class="hljs-number">2.0</span>, <span class="hljs-number">3.0</span>, <span class="hljs-number">2.0</span>, <span class="hljs-number">3.0</span>],
    [<span class="hljs-number">4.0</span>, <span class="hljs-number">4.0</span>, <span class="hljs-number">4.0</span>, <span class="hljs-number">4.0</span>],
])

<span class="hljs-comment"># ddof means degrees of freedom</span>
var_items = np.var(data, axis=<span class="hljs-number">0</span>, ddof=<span class="hljs-number">1</span>)
total_scores = np.sum(data, axis=<span class="hljs-number">1</span>)
var_total = np.var(total_scores, ddof=<span class="hljs-number">1</span>)
n = data.shape[<span class="hljs-number">0</span>]
correction_factor = n / (n - <span class="hljs-number">1</span>)
alpha = correction_factor * (<span class="hljs-number">1</span> - np.sum(var_items) / var_total)
print(<span class="hljs-string">f"Cronbach's Alpha: <span class="hljs-subst">{alpha:<span class="hljs-number">0.4</span>f}</span>"</span>)
</code></pre>
<p>As an alternative, below, a Rust function is shown as an implementation to calculate the Cronbach's Alpha. It receives as input a matrix where rows are respondents and columns are survey items.</p>
<pre><code class="lang-rust"><span class="hljs-function"><span class="hljs-keyword">fn</span> <span class="hljs-title">cronbach_alpha</span></span>(data: &amp;<span class="hljs-built_in">Vec</span>&lt;<span class="hljs-built_in">Vec</span>&lt;<span class="hljs-built_in">f64</span>&gt;&gt;) -&gt; <span class="hljs-built_in">f64</span> {
    <span class="hljs-keyword">let</span> n = data.len() <span class="hljs-keyword">as</span> <span class="hljs-built_in">f64</span>;
    <span class="hljs-keyword">let</span> d = data[<span class="hljs-number">0</span>].len();
    <span class="hljs-comment">// item variances</span>
    <span class="hljs-keyword">let</span> <span class="hljs-keyword">mut</span> var_items = <span class="hljs-built_in">Vec</span>::new();
    <span class="hljs-keyword">for</span> j <span class="hljs-keyword">in</span> <span class="hljs-number">0</span>..d <span class="hljs-keyword">as</span> <span class="hljs-built_in">usize</span> {
        <span class="hljs-keyword">let</span> col: <span class="hljs-built_in">Vec</span>&lt;<span class="hljs-built_in">f64</span>&gt; = data.iter()
            .map(|row| row[j]).collect();
        var_items.push(variance(&amp;col));
    }
    <span class="hljs-comment">// total score variances</span>
    <span class="hljs-keyword">let</span> total_scores: <span class="hljs-built_in">Vec</span>&lt;<span class="hljs-built_in">f64</span>&gt; = data.iter()
        .map(|row| row.iter().sum()).collect();
    <span class="hljs-keyword">let</span> var_total = variance(&amp;total_scores);
    <span class="hljs-comment">// cronbach's alpha</span>
    <span class="hljs-keyword">let</span> sum_var_items: <span class="hljs-built_in">f64</span> = var_items.iter().sum();
    <span class="hljs-keyword">let</span> correction_factor = n / (n - <span class="hljs-number">1.0</span>);
    correction_factor *
        (<span class="hljs-number">1.0</span> - (sum_var_items / var_total))
}
</code></pre>
<p>To compute the variance in the previous code, given that \(\sigma^2 = \frac{\sum(x_i - \bar{x})^2}{n - 1}\), one more function can be included:</p>
<pre><code class="lang-rust"><span class="hljs-function"><span class="hljs-keyword">fn</span> <span class="hljs-title">variance</span></span>(data: &amp;<span class="hljs-built_in">Vec</span>&lt;<span class="hljs-built_in">f64</span>&gt;) -&gt; <span class="hljs-built_in">f64</span> {
    <span class="hljs-keyword">let</span> n = data.len() <span class="hljs-keyword">as</span> <span class="hljs-built_in">f64</span>;
    <span class="hljs-keyword">let</span> mean = data.iter().sum::&lt;<span class="hljs-built_in">f64</span>&gt;() / n;
    <span class="hljs-keyword">let</span> sqr_diff: <span class="hljs-built_in">f64</span> = data.iter()
        .map(|x| (x - mean).powi(<span class="hljs-number">2</span>)).sum();
    sqr_diff / (n - <span class="hljs-number">1.0</span>)
}
</code></pre>
<p>To use these functions, here it is an example:</p>
<pre><code class="lang-rust"><span class="hljs-function"><span class="hljs-keyword">fn</span> <span class="hljs-title">main</span></span>() {
    <span class="hljs-comment">// rows are respondents</span>
    <span class="hljs-comment">// columns are responses to the survey items</span>
    <span class="hljs-keyword">let</span> responses = <span class="hljs-built_in">vec!</span>[
        <span class="hljs-built_in">vec!</span>[<span class="hljs-number">4.0</span>, <span class="hljs-number">4.0</span>, <span class="hljs-number">4.0</span>, <span class="hljs-number">5.0</span>],
        <span class="hljs-built_in">vec!</span>[<span class="hljs-number">3.0</span>, <span class="hljs-number">4.0</span>, <span class="hljs-number">3.0</span>, <span class="hljs-number">4.0</span>],
        <span class="hljs-built_in">vec!</span>[<span class="hljs-number">5.0</span>, <span class="hljs-number">4.0</span>, <span class="hljs-number">5.0</span>, <span class="hljs-number">5.0</span>],
        <span class="hljs-built_in">vec!</span>[<span class="hljs-number">2.0</span>, <span class="hljs-number">3.0</span>, <span class="hljs-number">2.0</span>, <span class="hljs-number">3.0</span>],
        <span class="hljs-built_in">vec!</span>[<span class="hljs-number">4.0</span>, <span class="hljs-number">4.0</span>, <span class="hljs-number">4.0</span>, <span class="hljs-number">4.0</span>],
    ];
    <span class="hljs-keyword">let</span> alpha = cronbach_alpha(&amp;responses);
    <span class="hljs-built_in">println!</span>(<span class="hljs-string">"Cronbach's Alpha: {:.4}"</span>, alpha);
}
</code></pre>
<p>Once that program is compiled and run, the output is like the below one. For this example, a value of 0.8761 indicates that a high internal consistency exists among the included survey items.</p>
<pre><code class="lang-bash">$ rustc cronbachalpha.rs
$ ./cronbachalpha 
Cronbach<span class="hljs-string">'s Alpha: 0.8761</span>
</code></pre>
<h2 id="heading-considerations">Considerations</h2>
<p>On using Cronbatch's Alpha estimations, researchers should attend some considerations, like:</p>
<ul>
<li>It is assumed that the set of items is measuring only one dimension. Other estimations, like Factor Analysis, can be used to identify the dimensions of a test.</li>
<li>An alpha is a property of a set of survey items for a sample of respondents. The alpha should be measured every time the test is administered (Streiner, 2003).</li>
<li>Alpha increases with the number of items and redundant questions. Therefore, a higher alpha can be the result not only because of the internal consistency, but because of the number of items or the redundancy among them.</li>
</ul>
<h2 id="heading-recommended-articles">Recommended articles</h2>
<ul>
<li>Sijtsma, K. (2009). On the Use, the Misuse, and the Very Limited Usefulness of Cronbach’s Alpha. Psychometrika, 74(1), 107–120. doi:10.1007/s11336-008-9101-0</li>
<li>Streiner, D. L. (2003). Starting at the beginning: an introduction to coefficient alpha and internal consistency. Journal of personality assessment, 80(1), 99-103.</li>
<li>Tavakol, M., &amp; Dennick, R. (2011). Making sense of Cronbach's alpha. International journal of medical education, 2, 53–55. <a target="_blank" href="https://doi.org/10.5116/ijme.4dfb.8dfd">https://doi.org/10.5116/ijme.4dfb.8dfd</a></li>
</ul>
<h2 id="heading-source-code">Source code</h2>
<ul>
<li><a target="_blank" href="https://gist.github.com/jailop/cb458a22800c2bce1e55289e9a2836fa">Python implementation</a></li>
<li><a target="_blank" href="https://gist.github.com/jailop/84563bd7a7e1d22897274ae9af40fb4e">Rust implementation</a></li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Bond Price and Yield]]></title><description><![CDATA[In this article, an exploration of bond valuation is presented. I describe the fundamental parameters of a bond. The key question is how to decide to invest in a bond compared to other alternatives. Current price and yield to maturity are used to ans...]]></description><link>https://findev.datainquiry.dev/bond-price-and-yield</link><guid isPermaLink="true">https://findev.datainquiry.dev/bond-price-and-yield</guid><category><![CDATA[bonds]]></category><category><![CDATA[Python]]></category><dc:creator><![CDATA[Jaime Lopez]]></dc:creator><pubDate>Thu, 27 Feb 2025 22:18:44 GMT</pubDate><content:encoded><![CDATA[<p>In this article, an exploration of bond valuation is presented. I describe the fundamental parameters of a bond. The key question is how to decide to invest in a bond compared to other alternatives. Current price and yield to maturity are used to answer that question. Additionally, I examine the inverse relationship between interest rates and bond prices. A Python's implementation is shown.</p>
<h2 id="heading-bond-parameters">Bond parameters</h2>
<p>The basic parameters of a bond are: (a) years to maturity (\(Y\)), (b) principal or face value (\(F\)), which is the amount that is returned to the investor at the end of the period; (c) coupon rate (\(c_r\)) or coupon value (\(CF\)) ; and (d) frequency of payments by year (\(f\)). The coupon value is an amount to be paid to the investor every year until maturity. The relation between coupon value and principal is given by the coupon rate: \(c_r = CF / F\).</p>
<p>To represent a bond in Python, we can use a data class. In this example, we are using the coupon rate as an attribute, instead of the coupon value. Besides that, we are assigning a default value for the payment frequency, to 1.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> dataclasses <span class="hljs-keyword">import</span> dataclass

<span class="hljs-meta">@dataclass</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Bond</span>:</span>
    principal: float
    cuppon_rate: float
    maturity_years: int
    payment_frequency: int = <span class="hljs-number">1</span>
</code></pre>
<p>For example, below a bond is defined with a face value of $1,000, a coupon rate of 5%, 3 years to maturity, and two payments by years.</p>
<pre><code class="lang-python">bond = Bond(
    principal=<span class="hljs-number">1000</span>,
    cuppon_rate=<span class="hljs-number">0.05</span>,
    maturity_years=<span class="hljs-number">3</span>,
    payment_frequency=<span class="hljs-number">2</span>,
)
</code></pre>
<h2 id="heading-current-price">Current price</h2>
<p>The decision to invest in a bond can be based on the estimated current price, i.e., how much money in current dollars represent the coupon and principal payments. To produce that estimation, we need a rate of discount (\(r\)), that can be an interest rate in case that current money can be invested in another stake, for example a certificate of deposit in a bank.</p>
<p>The formula to obtain a bond's current price is:</p>
<p>$$P = \sum_{t = 1}^{f \times Y} \frac{C/f}{(1 + \frac{r}{f})^t} + \frac{F}{(1+\frac{r}{f})^Y}$$</p><p>The first term is the sum of the current value of the coupon payments. The second term is the current value of the principal. If the frequency of payments by year is 1, that formula is reduced to:</p>
<p>$$P = \sum_{t = 1}^Y \frac{C}{(1 + r)^t} + \frac{F}{(1+r)^Y}$$</p><p>Below, it is an implementation of the current price formula as a Python function. When that function is used with the example bond defined above, if a rate of 6% is used, the result is $ 972.91. Given that result, if we have to pay $1,000.00 now to acquire that bond, we might be loosing $27.09.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">bond_price</span>(<span class="hljs-params">bond: Bond, r: float</span>) -&gt; float:</span>
    <span class="hljs-string">"""
    Computes the current price of a bond at the market rate `r`
    """</span>
    periods = bond.maturity_years * bond.payment_frequency
    cuppon = bond.principal * bond.cuppon_rate
    rate_factor = <span class="hljs-number">1</span> + r / bond.payment_frequency
    accum = np.sum([
        (cuppon / bond.payment_frequency) / rate_factor ** t
        <span class="hljs-keyword">for</span> t <span class="hljs-keyword">in</span> range(<span class="hljs-number">1</span>, periods + <span class="hljs-number">1</span>)
    ])
    accum += bond.principal / rate_factor ** periods
    <span class="hljs-keyword">return</span> accum
</code></pre>
<h2 id="heading-yield-to-maturity">Yield to maturity</h2>
<p>Another alternative to valuate a bond is, when given a current price, asking what internal rate that bond has. That internal rate is named <em>yield to maturity</em>. It is used to compare one bond acquisition to other investments alternatives based on return rates. In this case, for the previous formulas, we know \(P\) and we want to calculate \(r\).</p>
<p>As a Python function, below is an implementation to find the yield to maturity of a bond given a price. An iterative approximation is used based on the Newton's method. Using the <code>bond_yield</code> function with the example bond previously defined, if we use $972,91 as the price, the result will be 6.0%.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">bond_yield</span>(<span class="hljs-params">
    bond: Bond,
    price: float,
    max_iter = <span class="hljs-number">100</span>,
    tolerance = <span class="hljs-number">1e-5</span>
</span>) -&gt; float:</span>
    periods = bond.maturity_years * bond.payment_frequency
    cuppon = bond.principal * bond.cuppon_rate
    bond_yield = <span class="hljs-number">0.01</span>
    iterations = <span class="hljs-number">0</span>
    <span class="hljs-keyword">while</span> iterations &lt; max_iter:
        yield_price = bond_price(bond, bond_yield)
        diff = yield_price - price
        <span class="hljs-keyword">if</span> abs(diff) &lt; tolerance:
            <span class="hljs-keyword">break</span>
        bond_yield += diff / price * <span class="hljs-number">0.1</span>
        iterations += <span class="hljs-number">1</span>
    <span class="hljs-keyword">return</span> bond_yield
</code></pre>
<h2 id="heading-interest-rate-and-price">Interest rate and price</h2>
<p>Finally, it is important to understand the relation between the interest rate and the price of a bond. If the interest rate goes up, the price goes down. If the interest rate goes down, the price goes up. The relation is convex and inverse, as it is shown in the below figure. In different words, if the interest rate goes up, instead of putting money in a bond, we will be motivated to invest on another alternative with higher return.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> matplotlib.pyplot <span class="hljs-keyword">as</span> plt

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">plot_bond_price</span>(<span class="hljs-params">bond: Bond, x: np.ndarray, y: np.ndarray</span>):</span>
    plt.plot(x * <span class="hljs-number">100</span>, y / bond.principal * <span class="hljs-number">100</span>, color=<span class="hljs-string">"g"</span>)
    plt.axhline(y=<span class="hljs-number">100</span>, color=<span class="hljs-string">"r"</span>, label=<span class="hljs-string">"Face value"</span>)
    plt.ylabel(<span class="hljs-string">"Price (%)"</span>)
    plt.xlabel(<span class="hljs-string">"Yield (%)"</span>)
    plt.legend()

x = np.linspace(<span class="hljs-number">0.01</span>, <span class="hljs-number">1.0</span>, <span class="hljs-number">100</span>)
y = np.vectorize(<span class="hljs-keyword">lambda</span> r: bond_price(bond, r))(x)
plot_bond_price(bond, x, y)
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1740694114695/55caa8f7-80a5-4497-8d9f-b66332b68bd6.png" alt class="image--center mx-auto" /></p>
]]></content:encoded></item><item><title><![CDATA[Zig & Go Interoperation]]></title><description><![CDATA[Zig & Go can be a convenient combination of programming languages. Zig provides fine-grained control over memory and performance, making it ideal to solve low-level tasks (similar to C), while Go excels in simplicity, easy of development, and built-i...]]></description><link>https://findev.datainquiry.dev/zig-and-go-interoperation</link><guid isPermaLink="true">https://findev.datainquiry.dev/zig-and-go-interoperation</guid><category><![CDATA[zig]]></category><category><![CDATA[Go Language]]></category><dc:creator><![CDATA[Jaime Lopez]]></dc:creator><pubDate>Tue, 18 Feb 2025 17:47:19 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1739901986676/6589a457-44b1-4256-8af9-401e13a1ba77.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Zig &amp; Go can be a convenient combination of programming languages. Zig provides fine-grained control over memory and performance, making it ideal to solve low-level tasks (similar to C), while Go excels in simplicity, easy of development, and built-in concurrency. Zig can be used to write performance-critical components and let Go to manage the main application logic.</p>
<p>One way to enable this combination is by writing Zig functions that can be called as C functions, and interfacing those functions to Go using <code>cgo</code>. In other words, one strategy is using Zig as a C replacement and taking advantage of the features that Go has available for using C generated code.</p>
<pre><code class="lang-plaintext">const std = @import("std");

fn strlen(s: [*:0]const u8) u64 {
    return std.mem.len(s);
}

test "String Length" {
    const s = "Hello, world!";
    try std.testing.expect(strlen(s.ptr) == 13);
}
</code></pre>
<p>In the above Zig code (<code>example.zig</code>), a <code>strlen</code> function is defined. It receives as argument a C string, i.e. a null terminated string, and returns its length. To show that this library can be used as a C replacement, below is a C program (<code>client.c</code>) that calls our custom version of <code>strlen</code>.</p>
<pre><code class="lang-c"><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;assert.h&gt;</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;stddef.h&gt;</span></span>

<span class="hljs-function"><span class="hljs-keyword">extern</span> <span class="hljs-keyword">size_t</span> <span class="hljs-title">strlen</span><span class="hljs-params">(<span class="hljs-keyword">const</span> <span class="hljs-keyword">char</span> *s)</span></span>;

<span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">main</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-keyword">const</span> <span class="hljs-keyword">char</span> *s = <span class="hljs-string">"Hello, world!"</span>;
    assert(<span class="hljs-built_in">strlen</span>(s) == <span class="hljs-number">13</span>);
    <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
}
</code></pre>
<p>To compile and test these examples, you can use the below commands. A static library is created which is used when linking the C program to resolve the location of the <code>strlen</code> function. In other words, we are using the <code>strlen</code> function written in Zig, instead of the one provided by the C standard library. Because the assertion in <code>client.c</code> is true, if everything is correct, no output should be produced when the binary <code>client</code> is run.</p>
<pre><code class="lang-bash">$ zig <span class="hljs-built_in">test</span> example.zig
All 1 tests passed.
$ zig build-lib example.zig
$ gcc -o client client.c -L. -lexample
$ ./client
</code></pre>
<p>At this point, we have demonstrated that Zig can be used as a replacement for C. Now, we are able to use this example’s Zig code in a Go program. The below example (<code>demo.go</code>) is calling our custom <code>strlen</code> function in an assertion. According to the requirements of the <code>cgo</code> interface, we are declaring the library flags and the external function signature as pseudo-comments. Besides that, we are also taking care to allocate and de-allocate a proper c-string, to pass it as the argument for the <code>strlen</code> function.</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main

<span class="hljs-comment">// #cgo LDFLAGS : -L. -lexample</span>
<span class="hljs-comment">// #include &lt;stdlib.h&gt;</span>
<span class="hljs-comment">// extern size_t strlen(const char *s);</span>
<span class="hljs-keyword">import</span> <span class="hljs-string">"C"</span>
<span class="hljs-keyword">import</span> <span class="hljs-string">"unsafe"</span>

<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    s := <span class="hljs-string">"Hello, world!"</span>
    c_s := C.CString(s)
    <span class="hljs-keyword">defer</span> C.free(unsafe.Pointer(c_s))
    <span class="hljs-keyword">if</span> C.strlen(c_s) != <span class="hljs-number">13</span> {
        <span class="hljs-built_in">panic</span>(<span class="hljs-string">"Incorrect size"</span>)
    }
}
</code></pre>
<p>You can test the previous example, using the below commands. Similar to the C example, given that the assertion is true, if everything is correct, no output should be produced when the binary <code>demo</code> is run.</p>
<pre><code class="lang-bash">$ go build demo.go
$ ./demo
</code></pre>
<p>In this presentation, I have avoided to discuss the nuances of defining proper type signatures for your functions in order to pass arguments and return values between Zig and Go. For primitive data types, Go provides direct translations to C and Zig types. Beyond that, the usage of string as the type for the argument of <code>strlen</code>, shown in this article, can give you a clue that in the most of the cases, for structured data types, what your are passing are just pointers.</p>
<p>One final word about Zig &amp; Go, they both have out of the box cross-platform compatibility and scalability across different levels of computing. Instead of locking your projects to a restricting tooling, you can build relatively open components preserving at the same time performance and simplicity.</p>
]]></content:encoded></item><item><title><![CDATA[C Callbacks]]></title><description><![CDATA[Assume that you have a C function that accepts another function as an argument, mostly known as a callback. This is used to delegate processing data from one function to another, without pre-defining how that other function will work. Ex-post, the de...]]></description><link>https://findev.datainquiry.dev/c-callbacks</link><guid isPermaLink="true">https://findev.datainquiry.dev/c-callbacks</guid><category><![CDATA[C]]></category><category><![CDATA[callbacks]]></category><dc:creator><![CDATA[Jaime Lopez]]></dc:creator><pubDate>Mon, 17 Feb 2025 02:17:31 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1739759975261/f4f31b73-ebcd-4aa6-8586-cd70b4badc97.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Assume that you have a C function that accepts another function as an argument, mostly known as a callback. This is used to delegate processing data from one function to another, without pre-defining how that other function will work. Ex-post, the developer has the freedom to choose among different implementations of callback functions.</p>
<p>A basic example for a callback function is to delegate displaying a message. Assume that you are a library writer, so you anticipate that your library can be used by a command line application and by another with a graphical user interface. In the first case, a <code>printf</code> call can be enough to display in the console a message generated by your library. However, creating a dialog window to display that message can be required for the GUI application.</p>
<p>An example of callback functions (<code>example.c</code>): <code>iso_time</code> is a function that generates a string with the current time in ISO format. It receives as argument a callback function which is supposed to display that message. Once the current time is generated, the callback function is called to process the message.</p>
<pre><code class="lang-c"><span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;stdio.h&gt;</span></span>
<span class="hljs-meta">#<span class="hljs-meta-keyword">include</span> <span class="hljs-meta-string">&lt;time.h&gt;</span></span>

<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">iso_time</span><span class="hljs-params">(<span class="hljs-keyword">void</span> (*callback)(<span class="hljs-keyword">const</span> <span class="hljs-keyword">char</span> *))</span> </span>{
    <span class="hljs-keyword">time_t</span> now;
    time(&amp;now);
    callback(ctime(&amp;now));
}

<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">display_naked</span><span class="hljs-params">(<span class="hljs-keyword">const</span> <span class="hljs-keyword">char</span> *message)</span> </span>{
    <span class="hljs-built_in">puts</span>(message);
}

<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">display_labeled</span><span class="hljs-params">(<span class="hljs-keyword">const</span> <span class="hljs-keyword">char</span> *message)</span> </span>{
    <span class="hljs-built_in">printf</span>(<span class="hljs-string">"Time: %s"</span>, message);
}

<span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">main</span><span class="hljs-params">()</span> </span>{
    iso_time(display_naked);
    iso_time(display_labeled);
    <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
}
</code></pre>
<p>In the previous example, <code>display_naked</code> and <code>display_labeled</code> are alternatives of callback functions. They just print the message, but <code>display_labeled</code> includes a label before the message. The <code>main</code> function calls <code>iso_time</code> two times, passing as argument <code>display_naked</code> and <code>display_labeled</code> respectively. Compiling and running the program produces an output like it is shown below.</p>
<pre><code class="lang-bash">$ gcc -o example example.c
$ ./example
Sat Feb 15 22:23:39 2025

Time: Sat Feb 15 22:23:39 2025
</code></pre>
<p>Using callback functions is a valuable technique for modular software development, i.e. one in which different pieces are loosely coupled. Some modules can be easily updated and replaced to support multiple test and use cases. Furthermore, many widely used libraries and applications, like for network communications, gaming, and user interfaces, are supported by callback functions.</p>
]]></content:encoded></item></channel></rss>