Hey there if you are using anchor, you can do cpis in a "anchor way".
Also the account that is sending sol either the account is owned by the program(cpi with signer seeds) or needs to be the Signer/Owner.(simple cpi) ( ill show you the both options ) 



    
    use anchor_lang::{prelude::*, system_program::{Transfer, transfer}};

    #[program]
    mod hello_anchor {
    use super::*;
    pub fn initialize(ctx: Context<Initialize>, data: u64) -> 
    Result<()> {
        ctx.accounts.init(data, &ctx.bumps)?;
        msg!("Changed data to: {}!", data);
    }

    pub fn send_sol(ctx: Context<SendSol>, amount: u64) -> Result<()> 
    {
        ctx.accounts.send_sol(amount)
    }
    pub fn send_sol_pda(ctx: Context<SendSolPda>, amount: u64) -> 
    Result<()> {
        ctx.accounts.send_sol_pda(amount)
    }
    }
    //Owner Signer way
    #[derive(Accounts)]
    pub struct SendSol<'info> {
    #[account(mut)]
    pub sender: Signer<'info>,
    pub receiver: AccountInfo<'info>,
    pub system_program: Program<'info, System>,
    }

    impl<'info> SendSol<'info> {    
    pub fn send_sol(
        &mut self,
        amount:u64,
    ) -> Result<()> {       
        let accounts = Transfer {
            from: self.sender.to_account_info(),
            to: self.receiver.to_account_info()
        };

        let ctx = CpiContext::new(
            self.system_program.to_account_info(),
            accounts
        );

        transfer(ctx, amount)
    }
    }
    //PDa way
    #[derive(Accounts)]
    pub struct SendSolPda<'info> {
    #[account(
        seeds=[b"sender"],
        bump = sender.bump
    )]
    pub sender: Account<'info, SigningAccount>,
    pub receiver: AccountInfo<'info>,
    pub system_program: Program<'info, System>,
    }

    impl<'info> SendSolPda<'info> {    
    pub fn send_sol_pda(
        &mut self,
        amount:u64,
    ) -> Result<()> {       
        let accounts = Transfer {
            from: self.sender.to_account_info(),
            to: self.receiver.to_account_info()
        };
        let seeds = &[
            &b"sender"[..],
            &[self.sender.bump],
        ];

        let signer_seeds = &[&seeds[..]];

        let ctx = CpiContext::new(
            self.system_program.to_account_info(),
            accounts,
            signer_seeds
        );

        transfer(ctx, amount)
    }
    }

    #[derive(Accounts)]
    pub struct Initialize<'info> {
    #[account(
          init,
          payer = signer,          
          seeds = [b"sender"], 
          bump,
          space = SigningAccount::LEN
    )]
    pub new_account: Account<'info, SigningAccount>,
    #[account(mut)]
    pub signer: Signer<'info>,
    pub system_program: Program<'info, System>,
    }

    impl<'info> Initialize<'info> {
     pub const LEN: usize = 8 + 8 + 1
    pub fn init(
        &mut self, 
        bumps: &InitializeBumps,
        data: u64,
    ) -> Result<()> {
        
        self.new_account.set_inner(SigningAccount{ 
            data, 
            bump: bumps.new_account
    });
        Ok(())

    }

    }

    #[account]
    pub struct SigningAccount {
    data: u64,
    bump: u8,
    }
    


Notes: 

 1. Changed your send_sol function;
 2. Added send_sol_pda function;
 3. Fixed and added the normal cpi way;
 4. Added Pda Cpi;
 5. Also added a set_inner when initing the type SigningAccount accounts.