Saturday, December 31, 2022

ChatGPT Unity Graph Database Code Example

UPDATE: This code eventually worked, although I had to ask ChatGPT to also write the PriorityQueue class which it had originally left undeclared (I didn't include this part of the chat below - but reproducing what I ran shouldn't be too difficult for anyone who is interested in retracing my steps).  Running this code also ran into an exception in the sort function, which could be fixed by expanding the lambda function (I don't like those much anyways) into a full function which tested that both sort keys exist and if they don't just return 0 in the (formerly) lambda function for the sort.  Anyways... it all works as expected and helped me go forward with this coding idea in Unity.  If you want the full details, please let me know and I'll be happy to add them here.


 


https://chat.openai.com/chat

Frank Braker
write a graph database for the unity3d environment to be used with wavefunction collapse map generation and path finding

ChatGPT:

A graph database is a database that stores data in a graph structure, with nodes representing entities and edges representing relationships between those entities. In the context of the Unity3D environment, you might use a graph database to store information about the layout of a game level, such as the locations of objects, obstacles, and points of interest. This information could then be used to generate maps using wavefunction collapse algorithms and to perform pathfinding operations to navigate through the game level.

To create a graph database for use in Unity3D, you would first need to design the data model for your graph. This would involve determining the types of nodes and edges you will need to represent the data you want to store, and defining any properties or attributes that each node or edge might have.

Next, you would need to implement a data structure to store your graph in memory. There are several options you could consider for this, including adjacency lists, adjacency matrices, and edge lists. The choice of data structure will depend on the specific requirements of your application, including the size and complexity of the graph and the type of operations you will be performing on it.

Once you have implemented the data structure for your graph, you can then create functions to add and remove nodes and edges, as well as to query and manipulate the data stored in the graph. You may also want to consider implementing algorithms for wavefunction collapse map generation and pathfinding, such as Dijkstra's algorithm or A* search.

Finally, you would need to integrate your graph database into your Unity3D project, either by writing code to access the database from within your game or by using an existing plugin or library that provides this functionality. This would allow you to use the data stored in the graph to generate maps and perform pathfinding in your game.


Frank Braker
write the C# code for this

ChatGPT:
Here is an example of how you could implement a basic graph database in C# for use in the Unity3D environment:

using System;

using System.Collections.Generic;

 

// A node in the graph

public class Node {

  // The unique ID of the node

  public int ID { get; set; }

  // A dictionary of edges connecting this node to other nodes

  public Dictionary<int, Edge> Edges { get; set; }

  // Any additional properties or attributes of the node

  public object Data { get; set; }

 

  public Node(int id) {

    ID = id;

    Edges = new Dictionary<int, Edge>();

  }

}

 

// An edge in the graph, connecting two nodes

public class Edge {

  // The unique ID of the edge

  public int ID { get; set; }

  // The node at the start of the edge

  public Node Start { get; set; }

  // The node at the end of the edge

  public Node End { get; set; }

  // The weight of the edge, if applicable

  public int Weight { get; set; }

  // Any additional properties or attributes of the edge

  public object Data { get; set; }

 

  public Edge(int id, Node start, Node end, int weight = 0) {

    ID = id;

    Start = start;

    End = end;

    Weight = weight;

  }

}

 

// The graph itself

public class Graph {

  // A dictionary of all the nodes in the graph

  public Dictionary<int, Node> Nodes { get; set; }

  // A dictionary of all the edges in the graph

  public Dictionary<int, Edge> Edges { get; set; }

 

  public Graph() {

    Nodes = new Dictionary<int, Node>();

    Edges = new Dictionary<int, Edge>();

  }

 

  // Add a new node to the graph

  public void AddNode(int id, object data = null) {

    Nodes[id] = new Node(id) { Data = data };

  }

 

  // Add a new edge to the graph

  public void AddEdge(int id, Node start, Node end, int weight = 0, object data = null) {

    var edge = new Edge(id, start, end, weight) { Data = data };

    start.Edges[id] = edge;

    Edges[id] = edge;

  }

 

  // Remove a node and all its connected edges from the graph

  public void RemoveNode(int id) {

    var node = Nodes[id];

    foreach (var edge in node.Edges.Values) {

      Edges.Remove(edge.ID);

    }

    Nodes.Remove(id);

  }

 

  // Remove an edge from the graph

  public void RemoveEdge(int id) {

    var edge = Edges[id];

    edge.Start.Edges.Remove(id);

    Edges.Remove(id);

  }

}

This code defines a Node class to represent a node in the graph, an Edge class to represent an edge connecting two nodes, and a Graph class to represent the graph itself. The Graph class has functions to add and remove nodes and edges, as well as a

EDIT: Here ChatGPT never finished its sentence, but that's fine.

Frank Braker
write a pathfinding function to find the fastest path between 2 nodes, which returns a list of all intermediate nodes take to form the path

ChatGPT:
Here is an example of a pathfinding function that you could use to find the fastest path between two nodes in a graph, using the Dijkstra algorithm:

using System;

using System.Collections.Generic;

 

// Find the fastest path between two nodes in the graph using Dijkstra's algorithm

public List<Node> FindFastestPath(Graph graph, Node start, Node end) {

  // Set up a priority queue to store the nodes we need to visit

  var queue = new PriorityQueue<Node>();

 

  // Set up a dictionary to store the distance from the start node to each node

  var distances = new Dictionary<Node, int>();

  // Set the distance to the start node to 0, and all other nodes to infinity

  distances[start] = 0;

  foreach (var node in graph.Nodes.Values) {

    if (node != start) {

      distances[node] = int.MaxValue;

    }

  }

 

  // Set up a dictionary to store the previous node on the fastest path from the start node to each node

  var previous = new Dictionary<Node, Node>();

 

  // Add the start node to the queue

  queue.Enqueue(start, 0);

 

  // While there are still nodes in the queue

  while (queue.Count > 0) {

    // Dequeue the node with the lowest distance

    var current = queue.Dequeue();

 

    // If we have reached the end node, we can stop the search

    if (current == end) {

      break;

    }

 

    // For each neighbor of the current node

    foreach (var neighbor in current.Edges.Values) {

      // Calculate the distance from the start node to the neighbor through the current node

      var distance = distances[current] + neighbor.Weight;

 

      // If the distance from the start node to the neighbor through the current node is shorter than the current distance from the start node to the neighbor

      if (distance < distances[neighbor.End]) {

        // Update the distance from the start node to the neighbor

        distances[neighbor.End] = distance;

        // Update the previous node on the fastest path from the start node to the neighbor

        previous[neighbor.End] = current;

        // Add the neighbor to the queue with the updated distance

        queue.Enqueue(neighbor.End, distance);

      }

    }

  }

 

  // If we have a path from the start node to the end node

  if (previous.ContainsKey(end)) {

    // Create a list to store the nodes on the fastest path

    var path = new List<Node>();

    // Set the current node to the end node

    var current = end;

    // While we have not reached the start node

    while (current != start) {

      // Add the current node to the beginning of the list

      path.Insert(0, current);

      // Set the current node to the previous node on the path

      current = previous[current];

    }

    // Add the start node to the beginning of the list

    path.Insert(0, start);

    // Return the list of nodes on the fastest path

    return path;

  }

  // If there is no path from the start node to the end node, return an empty list

  return new List<Node>();

}


Frank Braker
write example C# code that creates a map comprised of several nodes and edges, and which uses the pathfinding function, using the graph database code and pathfinding above

ChatGPT:

Here is an example of C# code that creates a map comprised of several nodes and edges, and uses the pathfinding function to find the fastest path between two nodes:


using System;

using System.Collections.Generic;

 

public static void Main() {

  // Create a new graph

  var graph = new Graph();

 

  // Add some nodes to the graph

  graph.AddNode(0, "Node 0");

  graph.AddNode(1, "Node 1");

  graph.AddNode(2, "Node 2");

  graph.AddNode(3, "Node 3");

  graph.AddNode(4, "Node 4");

  graph.AddNode(5, "Node 5");

 

  // Add some edges to the graph, with weights indicating the cost to travel along the edge

  graph.AddEdge(0, graph.Nodes[0], graph.Nodes[1], 10);

  graph.AddEdge(1, graph.Nodes[0], graph.Nodes[2], 5);

  graph.AddEdge(2, graph.Nodes[1], graph.Nodes[3], 1);

  graph.AddEdge(3, graph.Nodes[1], graph.Nodes[4], 2);

  graph.AddEdge(4, graph.Nodes[2], graph.Nodes[1], 3);

  graph.AddEdge(5, graph.Nodes[2], graph.Nodes[4], 9);

  graph.AddEdge(6, graph.Nodes[3], graph.Nodes[2], 2);

  graph.AddEdge(7, graph.Nodes[3], graph.Nodes[5], 4);

  graph.AddEdge(8, graph.Nodes[4], graph.Nodes[3], 6);

  graph.AddEdge(9, graph.Nodes[4], graph.Nodes[5], 2);

 

  // Find the fastest path from node 0 to node 5

  var path = FindFastestPath(graph, graph.Nodes[0], graph.Nodes[5]);

 

  // Print the IDs of the nodes on the fastest path

  Console.WriteLine("Fastest path from node 0 to node 5:");

  foreach (var node in path) {

    Console.WriteLine(node.ID);

  }

}

This code creates a new graph and adds six nodes and ten edges to it. It then uses the FindFastestPath function to find the fastest path from node 0 to node 5, and prints the IDs of the nodes on the path to the console. The output of this code would be:

Fastest path from node 0 to node 5:

0

2

1

3

5





Tuesday, June 14, 2022

Optimal Buy and Sell Estimation Using BetterInvesting.com

Optimal Buy and Sell Estimation Using BetterInvesting.com

Authored by: Frank Braker


Disclaimer: None of the words, thoughts, concepts, images or ideas in this post should be construed as financial advice of any kind.  This is a discussion of the features of a tool and not a recommendation of any financial strategy.  If you trade stocks, you assume all trading risks yourself.

I recently started using BetterInvesting.com.  In this guide you will learn about tools found there.


What The Tools Provide

These tools allow answering the following questions:

  • Is a company healthy?

    In the vast ocean of publicly tradable companies, we find a spectrum of varying degrees of company health, from the highly profitable to those that will soon declare bankruptcy.  Within seconds any given company can be visually understood in terms of Sales relative to competitors, Sales growth, Earnings per Share, Stock price, Pre-tax profit on Sales, ROE (return on equity), Total Debt, and Debt to Capital.  These indicators are presented visually to allow seeing long-term trends.

  • Should I buy this company now?  Sell it?  How can I tell?

    Forecasting high and low estimated prices based on historical data and fundamentals allows a methodical process for determining where to buy and where to sell - no more guessing or hoping for a price that may never happen.


2 stock research tools are provided at BetterInvesting.com:

  • CoreSSG: this is “the tutorial” mode of the toolset.  Use this for guidance and a detailed explanation of each step in evaluating a company.  A limited number of stock symbols can be fully evaluated for free in the trial version of BetterInvesting.com

  • SSGPlus: this is “the advanced” mode of the toolset which offers a condensed overview in a few screens.


Price

To complete this guide, you won’t have to pay anything.  When you are finished, consider buying the tools to open an account at Betterinvesting.com.  The price is roughly $10/month for the full suite of tools, and a marginally cheaper price for the “basic” tools.  I recommend buying the full suite for a full year as it is relatively affordable, especially for the service the tools provide.

Workflow

If you go to BetterInvesting.com - there’s a lot of interesting fluff to read.  You can join groups and spend time reading the site wondering what all this is.

Instead of wondering what this is, open this link instead:
https://ssg.betterinvesting.org/trial/ssgplus.aspx?ticker=fds

Notice that I have highlighted “ssgplus” in the link.  We’ll see why, below, but first have a look at the screen the link gives - it will look something like this:


This is the advanced tool.  For a summary screen of determining a company’s health, make sure the green “sales”, pink “pre-tax profit” and the blue “EPS (earnings per share)” are all sloping upwards from left to right.  Other criteria under “Legend” on the right can also be enabled.

For a deeper understanding of the meaning of the summary screen above, let’s switch to the CoreSSG tool by opening the URL below (this is the same URL as above, only ‘ssgplus’ is changed to ‘coressg’):
https://ssg.betterinvesting.org/trial/coressg.aspx?studyid=14852657&sk=48125


You could change which stock symbol you are looking at by clicking on “Quick Navigation”, but in the trial version only a few different symbols will be available.  Let’s discuss a little about how to find good stocks to analyze in the next section.

Finding Good Stocks

The full product does have a ‘heat map’ of studies other BetterInvesting users have done, which is a good method for finding stocks to look at.  There are more brute force methods such as using scripts to open the website in a browser to quickly navigate many symbols, see at a glance whether they are interesting, and look at hundreds of symbols in one sitting to try to find “hidden gems”.  This method won’t be discussed here, and is of nominal advantage over using the heat map (as companies that aren’t generating a lot of news buzz won’t see a lot of market volume either).

Using The CoreSSG Tool

The screen you brought up (here’s the link again) should look as shown in the screenshot below
https://ssg.betterinvesting.org/trial/coressg.aspx?studyid=14852657&sk=48125 :




Because CoreSSG is like a “tutorial mode” - it provides “Back” and “Next buttons to go through all the steps for evaluating a stock (just under the “Analyze Growth” button shown below:

You can study the notes given in the “Education” field which are very helpful:


Here are screenshots for each step of CoreSSG.  Again, the Education field provides good background for what is shown in each screenshot.  There will be some additional discussion provided below.

Figure 1: Historical Sales


Figure 2: Historical Earnings Per Share

Figure 3: Historical Stock Price Review


Figure 4: % Pre-Tax Profit on Sales


Figure 5: % Return on Equity


Figure 6: Total Debt


Figure 7: % Debt to Capital


Figure 8: Forecast Sales


Figure 8: Forecast Sales is the first screen in CoreSSG which requires filling in the “Enter Your 5 Year Annual Sales Growth Rate Forecast (%)” field.  Try using the same value as shown under “Growth Rate(%)” in the lower left corner of the screen, or adjust your estimate according to the current economic situation (i.e. is the economy booming, or going into a recession, etc.).  There are other details provided in the “Education” field too.

Figure 9: Forecast Earnings


Similarly, Figure 9: Forecast Earnings asks that you fill in the EPS Growth Rate Forecast (%) field.

By filling in these forecasts of Sales and Earnings, high and low estimates of PE and EPS give a basis for the high and low price estimates which will establish when to buy and when to sell, based on these forecasts.  We’ll see this in later steps below.


Figure 10: Forecast High Price

The forecast high price is calculated from your average high PE forecast multiplied by your high EPS forecast.  In Figure 10: Forecast High Price, values of 30 and 15 were entered for MSFT, which will be different for whatever symbol is being evaluated.  After entering these values, be sure to click “Update Study”.


Discussion

Forecasting the future PE, in practice, simply means putting in a reasonable number based on the 2 average P/E values shown in the lower left of the screen (just above the “Update Study” button).  Find the EPS forecast of “Figure 9: Forecast Earnings”, marked as “Analyst Consensus Estimate: EPS Long Term Estimate” shown in the figure as 13.8%.

It is worth noting: the more “glamorous” a stock is, the more “enthusiastic” (or perhaps “insane”) the market tends to be.  The market will pay less attention to company fundamentals and more on hype.  So as a result, the PE forecast will be higher than a more glamorous stock.  I.e. the price will be higher, regardless of earnings, for such a stock.

You will probably start to notice that, when comparing stocks and all other things being equal (for example earnings), the price will be inflated or deflated relative to the “glamor” of a stock.  For a less popular stock with excellent fundamentals, the PE will tend to be lower than if it is a well-known brand name with the same fundamentals or worse.  You will start to see a range of low PE which marks a good support price (where investors will buy the stock, causing it to go up in price, when it had previously been falling), and that range of low PE will be specific to that symbol, according to how glamorous that stock is.  NOTE: It begs the question, do some companies inflate their brand-name even when they have poor fundamentals, in order to inflate stock price?  By using these tools, we can avoid such companies by getting a clear picture of their fundamentals (both current and historical).


Figure 11: Forecast Low Price


For Figure 11: Forecast Low Price, follow a similar process as you did for Figure 10: Forecast High Price.


Figure 12: Assess Stock Price


Figure 12: Asses Stock Price provides a range of prices that indicate where to place a buy order, and where to place a sell order, using your previous estimates.  It will show “Invalid” if there are any issues with the estimates you provided.


Figure 13: Determine Potential Gain vs. Loss

In Figure 13: Determine Potential Gain vs Loss, the “Upside Downside Ratio” gives the probably of gain versus loss - and is recommended that at least 3 times the probability of gain makes an investment desirable.

Figure 14: Determine 5 Year Potential


This figure shows the annual rate of return assuming you are able to trade at the forecast high and low P/E.


Figure 15: Notes


Staff, community and your own notes can be accessed here.



Example Analysis
Here is an example. To generate this, I brought up a yearly chart of SWKS from 2017 to 2021, with the PE ratio as a charted indicator, and could from that, year by year, determine the yearly high and yearly low PE ratio. I could that way generate the 5 year averages by hand. But because the current year's low PE is far below this average, I had to skew both the high and low averages to a possible new low PE this year (possibly even lower than what we have right now). You should see those adjusted high and low PE estimates presented here:




Summary

By using the CoreSSG or SSGPlus tools, you can remove the guesswork of how healthy a company is, and calculate buy and sell prices for trading that company. Compared to technical trading, this is a very slow strategy that depends on yearly cycles, rather than short-term news events, to drive when to get in and out of a position.