So I am trying to find a way to allow OR operations on the front-end of my app and then translate the condition on the back-end server which then will talk to Intrinio (Financial Data API). The endpoint that I am trying to use (to save on api call credits) only allows for the AND operator but I am hoping there is some sort of way around this.
Here is the endpoint I am trying to use: http://docs.intrinio.com/#securities-search-screener
Here is just an example condition that I would be sending to my server to be translated:
open_price > 10 && (current_volume > 1000000 || current_volume > average_volume)
P.S open_price, current_volume, and average_volume are all tags used within the Intrinio ecosystem
I should probably also mention that they don't have NOTs
I implore you guys to look at the link before commenting...
In general, you can't.
In this API, you can negate atomic conditions only, changing ~gt~
to ~lte~
etc., e. g. changing open_price~gt~10
to open_price~lte~10
.
But you can't negate non-atomic conditions in this API, in particular you can't use De Morgan's laws.
There are only 3n (+1) boolean functions of n variables, which are expressible using conjunction and atomic negation. The total number of boolean functions of n variables is 22ⁿ. By the way, all of them are expressible using conjunction and non-atomic negation. Thus, there exist boolean functions that are not expressible using conjunction and atomic negation.
You should make two or more requests and then union results on an API client. There are a few ways to do it that are differ in number of requests, in total number of records retrieved (some records might be retrieved more than once), and in API call credits required (it is equal to the number of conditions).
Let's suppose that original data looks as follows (let's skip the open_price
attribute).
{
{
"identifier": "A-OK",
"current_volume": 1000002, "average_volume": 1000001
},
{
"identifier": "B-OK",
"current_volume": 1000001, "average_volume": 999999
},
{
"identifier": "D-OK",
"current_volume": 999999, "average_volume": 999998
},
{
"identifier": "E-OK",
"current_volume": 1000001, "average_volume": 1000002
},
{
"identifier": "G-NO",
"current_volume": 999999, "average_volume": 1000001
},
{
"identifier": "H-NO",
"current_volume": 999998, "average_volume": 999999
}
}
You need to retrieve records with identifiers A-OK
, B-OK
, D-OK
, E-OK
.
Approach 1 (two requests, resultsets are not disjoint)
current_volume~gt~1000000
current_volume~gt~average_volume
As you can see, we just perform disjunction on a client, not on a server...
Approach 2 (three requests, resultsets are disjoint)
current_volume~gt~1000000,current_volume~gt~average_volume
current_volume~gt~1000000,current_volume~lte~average_volume
current_volume~lte~1000000,current_volume~gt~average_volume
In this approach, we rely on this fact: A||B
is equal to (A && B) ^^ (A && !B) ^^ (!A && B)
.
Approach 3 (two requests, resultsets are disjoint)
current_volume~gt~1000000
current_volume~lte~1000000,current_volume~gt~average_volume
In this approach, we rely on this fact: A||B
is equal to A ^^ (!A && B)
.
Approach 4 (two requests, resultsets are disjoint)
In your particular case, there exists an approach that relies on the transitivity of the order relation on real numbers.
average_volume~gt~1000000,current_volume~gt~1000000
average_volume~lte~1000000,current_volume~gt~average_volume
However, this approach does not give much profit in terms of API call credits.
Comparison
+----------+----------+-----------+--------------+----------+
| Approach | Number of| Records | Resultsets | Total |
| | requests | retrieved | disjointness | credits |
+----------+----------+-----------+--------------+----------+
| # 1 | 2 | 6 (3+3) | no | 2 |
| # 2 | 3 | 4 | yes | 6 |
| # 3 | 2 | 4 | yes | 3 |
| # 4 | 2 | 4 | yes | 4 |
+----------+----------+-----------+--------------+----------+